购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 EXT

EXT文件系统全称是扩展文件系统(Extended File System),是Linux默认支持的文件系统。最早的EXT文件系统出现在1992年,其后经过不断发展,先后出现了四个版本:EXT1、EXT2、EXT3和EXT4。

2.2.1 EXT的发展概况

1992年,第1个扩展文件系统(EXT1)在Linux0.96c内核中实现,它第一次使用了虚拟文件系统(VFS)交换技术,可以支持的最大文件系统为2GB。

1993年1月第2个版本的扩展文件系统(EXT2)被引入Linux。相比于EXT1,它从UNIX文件系统中吸取了很多优点,从而成为Linux上第一个商业级文件系统。EXT2在磁盘上存储的(与磁盘功能相关的)数据结构中预留了很多空间供未来进一步开发使用,这也使得它具有很好的可扩展性。EXT2能够支持的最大文件系统达到2TB。

2001年11月第3个版本的扩展文件系统(EXT3)被引入Linux,它继承了EXT2的全部优点,还在可用性、数据完整性、速度和易于迁移四个方面有较大改进。EXT3还采用了日志技术,在系统突然发生故障的情况下,可以大大提高文件系统的可靠性。在EXT3文件系统中,如果使用4KB大小的数据块和32位的块号,所支持的最大文件系统能达到16TB。

第4个版本的扩展文件系统(EXT4)在性能、伸缩性和可靠性等方面进行了大量的改进,并引入了诸多新的技术,如引入区段(Extent)管理块,以及与块管理相关的延迟分配技术等。EXT4首先在Linux2.6.19内核中实现并得到应用,在2.6.28内核中稳定下来(2008年12月)。EXT4采用了48位块号和区段映射技术,这不仅增大了文件系统的容量,还改进了对大文件的访问效率,在使用4KB大小的数据块时,EXT4可以支持的最大文件系统为1EB。

2.2.2 树形目录结构

EXT文件系统采用一个独立的顶级树形目录架构(即所有一切都从root根目录开始,延伸到子目录)来组织和管理全部文件。目录文件记录了本目录下所有文件和子目录的信息(文件名和索引节点号inode),并依次存放在数据块中,采用把文件名(放在目录文件中)与文件的其他所有属性(放在索引节点inode表中)分开存储的管理方法来大大提高文件检索的速度,如图2-4所示。

图2-4 EXT文件系统的树形结构

2.2.3 EXT的磁盘布局

EXT2是Linux上标准的文件系统,EXT3是在EXT2基础上增加日志形成的,其思想可以追溯到早期UNIX家族发展的基于超级块和inode的经典概念,EXT4是EXT3的进一步升级。因此,本节以EXT2为模板介绍EXT文件系统的磁盘布局。图2-5为EXT2文件系统的磁盘布局。

在EXT文件系统中,存储的最小单位是块(block),一个块究竟多大是在格式化时确定的,如可以设定块大小为1024、2048或4096字节,一旦文件系统创建好以后,块的大小就不能改变了。这些块被聚在一起分成几个大的块组(block group)。每个块组中有多少个块是固定的(最后一个块组除外,其所管理的块可能会少一些)。而启动块(boot block)的大小是确定的,即1KB,启动块由PC标准规定,用来存储磁盘分区信息和启动信息,任何文件系统都不能使用启动块。启动块之后才是EXT文件系统的开始,EXT文件系统将整个分区划成若干个同样大小的块组,每个块组都由以下部分组成:超级块(super block)、块组描述符表(GDT)、预留块组描述符表(reserved GDT)、块位图(block bitmap)、节点位图(inode bitmap)、节点表(inode table)和数据块(data block)。

图2-5 EXT2文件系统的磁盘布局

1.超级块

超级块存储了EXT文件系统的全局配置参数(如数据块大小、总块数和索引节点总数等,这些参数在文件系统创建时就确定下来了)和动态信息(如当前空闲块数和空闲索引节点数等,可以在运行中改变)。对超级块的访问必须是互斥的,即任一时刻最多只能有一个进程访问超级块。

原始做法是在每一个块组中都保留一个超级块的备份,在系统启动时内核读入块组0中的超级块到内存中,其他块组的备份只用于当块组0的超级块损坏时。当采用sparse superblock技术时,超级块、块组描述符表和预留块组描述符表只写入到块组0、1,以及其他块组号可以表示为3、5、7的幂的块组中。这是现在的默认技术,除非在创建文件系统时指定屏蔽它。

由于每个分区的块组0的特殊性,最开始的1024字节(即0~1号扇区)并未使用,而是留给了引导区。所以,从分区的第1024字节开始为超级块开始的位置。而块组1及其后面的块组没有引导区,也就没有上述1024字节的填充,块组从超级块开始。对超级块的数据结构定义在内核文件/include/Linux/EXT4_fs.h中,超级块中包含的内容及每个字段的意义如图2-6所示。

图2-6 超级块的内容

在超级块中,魔术标签是一个很重要的字段,在EXT2/EXT3/EXT4中,这个字段的值为0xEF53,否则这个分区就不是一个正常的EXT2/EXT3/EXT4文件系统。

另一个重要的字段是每个块占用的字节数,其对应的数据结构是s_log_block_size,标识文件系统中块的大小(以字节为单位)为(B=1<<(s_log_block_size+10))。例如,如果值为0时,则块的大小为1024B,也是最小的块大小;如果值为2,那么块的大小为4096B。

2.块组描述符表

块组描述符表(GDT,Group Descriptor Table)由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。每个块组描述符存储一个块组的描述信息,如在这个块组中从哪里开始是inode表、从哪里开始是数据块、空闲的inode和数据块还有多少个等。与超级块类似,块组描述符表在每个块组的开头也都有一份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据。通常内核只用到第0个块组中的拷贝,当执行e2fsck检查文件系统一致性时,第0个块组中的超级块和块组描述符表就会拷贝到其他块组,这样当第0个块组的开头意外损坏时就可以用其他拷贝来恢复,从而减少损失。

3.块位图

一个块组中的块是这样利用的,数据块存储所有文件的数据,比如某个分区的块大小是1024字节,某个文件是2049字节,那么就需要三个数据块来存储,即使第三个块只存储一字节也需要占用一个整块;超级块、块组描述符表、块位图、inode位图、inode表这几部分存储该块组的描述信息。那么如何知道哪些块已经用来存储文件数据或其他描述信息,哪些块仍然空闲可用呢?块位图就是用来描述整个块组中哪些块已用、哪些块空闲的,它本身占一个块,其中的每位代表本块组中的一个块,该位为1表示该块已用,为0表示该块空闲可用。

4.节点位图

与块位图类似,本身占一个块,其中每位表示一个inode是否空闲可用。

5.节点表

我们知道,一个文件除了数据需要存储之外,一些描述信息也需要存储,如文件类型(常规、目录、符号链接等)、权限、文件大小、创建/修改/访问时间等,这些信息存在inode中而不是数据块中。每个文件都有一个inode,一个块组中的所有inode组成了inode表(节点表)。

inode表占多少个块在格式化时就要决定并写入块组描述符中,mke2fs格式化工具的默认策略是一个块组有多少个8KB就分配多少个inode。由于数据块占了整个块组的绝大部分,也可以近似认为数据块有多少个8KB就分配多少个inode,换句话说,如果平均每个文件的大小是8KB,当分区存满的时候inode表会得到比较充分的利用,数据块也不浪费;如果这个分区存的都是很大的文件(比如电影),则数据块用完的时候inode会有一些浪费;如果这个分区存的都是很小的文件(比如源代码),则有可能数据块还没用完inode就已经用完了,数据块可能有很大的浪费。如果用户在格式化时能够对这个分区以后要存储的文件大小进行预测,也可以用mke2fs的-i参数手动指定每多少字节分配一个inode。

6.数据块

根据不同的文件类型有以下几种情况:

1)对于常规文件,文件的数据存储在数据块中。

2)对于目录,该目录下的所有文件名和目录名存储在数据块中,注意文件名保存在它所在目录的数据块中,除文件名之外,ls-l命令看到的其他信息都保存在该文件的inode中。注意这个概念:目录也是一种文件,是一种特殊类型的文件。

3)对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。

4)设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中。

2.2.4 数据块寻址方法

如果一个文件有多个数据块,这些数据块很可能不是连续存放的,应该如何寻址到每个块呢?实际上,根目录的数据块是通过其inode中的索引项Blocks[0]找到的,事实上这样的索引项一共有15个,从Blocks[0]到Blocks[14],每个索引项占4字节。前12个索引项都表示块编号,如Blocks[0]字段保存着24,就表示第24个块是该文件的数据块,如果块大小是1KB,这样可以表示从0~12KB的文件。如果剩下的三个索引项Blocks[12]到Blocks[14]也是这么用的,就只能表示最大15KB的文件了,这是远远不够的,事实上,剩下的三个索引项都是间接索引。如图2-7所示。

图2-7 EXT3文件数据块的组织示意图

索引项Blocks[12]所指向的块并非数据块,而是称为间接寻址块(Indirect Block),其中存放的都是类似Blocks[0]这种索引项,再由索引项指向数据块,设块大小为b,那么一个间接寻址块中可以存放b/4个索引项,指向b/4个数据块。所以如果把Blocks[0]到Blocks[12]都用上,最多可以表示b/4+12个数据块,对于块大小是1KB的情况,最大可表示268KB的文件。二级索引指针可以管理的文件大小为64MB,三级索引指针可以管理的文件大小为16GB。

表2-2列出了EXT文件系统设置不同大小的数据块时,文件和文件系统的限长。

表2-2 每块的字节数与文件系统最大长度的关系

在EXT3中,对于大文件来说,存放数据需要经过几级间接索引,这就导致了存取大文件数据时的性能比较差。在实际应用中,测试表明数据不连续的情况不会超过10%,所以在EXT4中引入了区段的概念来表示文件数据所在的位置。区段是用来描述保存文件数据所使用的连续物理块的一段范围。每个区段由EXT4_EXTent结构类型来定义,占12字节,区段的结构类型定义在内核文件/include/Linux/EXT4_fs_EXTents.h中。

2.2.5 日志系统

对文件的存储包括对文件数据(data)和文件属性(元数据,metadata)的存储。为了在意外情况(如系统崩溃)下,可以通过恢复程序保证数据的一致性和完整性,EXT3文件系统引入了日志的概念,EXT4还能对日志进行校验和,确保有效的数据变更能够在底层文件系统上正确完成。EXT3/4日志存放在journal文件中,并提供了三种日志的记录方式:

1)data=writeback方式:在这种方式下,EXT3文件系统只对元数据写日志。虽然这会让最近修改的文件在出现意外事件时损坏,但可以得到较高的速度。

2)data=ordered方式(默认方式):在这种方式下,EXT3文件系统也只将元数据写入日志系统,但还把对数据的每一次更新都作为一个事务写入相关文件中,这样有效地解决了第一种方式中文件数据被损坏的问题。但是文件系统的运行速度要稍慢些,且不能解决文件数据被覆盖时系统崩溃而无法恢复的问题。

3)data=journal方式:在这种方式下,EXT3文件系统提供了完整的文件数据和元数据的日志记录,再写入它的最终位置。这样在系统崩溃时,就可以通过日志来完全修复,保证文件数据和元数据的一致性。

2.2.6 EXT4引入的新特性

(1)相当大的文件系统和更大的文件

EXT3文件系统最多只能支持32TB的文件系统和2TB的文件,根据使用的具体架构和系统设置,实际容量上限可能比这个数字还要低,即只能容纳2TB的文件系统和16GB的文件。而EXT4的文件系统容量达到1EB,而文件容量则达到16TB,这是一个非常大的数字了。对一般的台式机和服务器而言,这可能并不重要,但对于大型磁盘阵列的用户而言,这就非常重要了。

(2)更多的子目录数量

EXT3目前只支持32000个子目录,而EXT4取消了这一限制,理论上支持无限数量的子目录。

(3)更多的块和inode节点数量

EXT3文件系统使用32位空间记录块数量和inode节点数量,而EXT4文件系统将它们扩充到64位。

(4)多块分配

当数据写入EXT3文件系统中时,EXT3的数据块分配器每次只能分配一个4KB的块,如果写一个100MB的文件就要调用25600次数据块分配器,而EXT4的多块分配器(Multiblock Allocator,MBAlloc)支持一次调用分配多个数据块。

(5)持久性预分配

如果一个应用程序需要在实际使用磁盘空间之前对它进行分配,大部分文件系统都是通过向未使用的磁盘空间写入0来实现分配的,比如P2P软件。为了保证下载文件有足够的空间存放,常常会预先创建一个与所下载文件大小相同的空文件,以免未来的数小时或数天之内磁盘空间不足导致下载失败。而EXT4在文件系统层面实现了持久预分配并提供相应的API,比应用软件自己实现更有效率。

(6)延迟分配

EXT3的数据块分配策略是尽快分配,而EXT4的策略是尽可能地延迟分配,直到文件在缓冲中写完才开始分配数据块并写入磁盘,这样就能优化整个文件的数据块分配,显著提升性能。

(7)盘区结构

EXT3文件系统采用间接映射地址,当操作大文件时,效率极其低下。例如,一个100MB大小的文件,在EXT3中要建立25600个数据块(以每个数据块大小为4KB为例)的映射表;而EXT4引入了盘区概念,每个盘区为一组连续的数据块,上述文件可以通过盘区的方式表示为“该文件数据保存在接下来的25600个数据块中”,提高了访问效率。

(8)新的inode节点结构

EXT4支持更大的inode节点。之前的EXT3默认的inode节点大小为128字节,EXT4为了在inode节点中容纳更多的扩展属性,默认inode节点大小为256字节。另外,EXT4还支持快速扩展属性和inode节点保留。

(9)日志校验功能

日志是文件系统最常用的结构,日志也很容易损坏,而从损坏的日志中恢复数据会导致更多的数据损坏。EXT4给日志数据添加了校验功能,日志校验功能可以很方便地判断日志数据是否损坏。而且EXT4将EXT3的两阶段日志机制合并成一个阶段,在增加安全性的同时提高了性能。

(10)支持“无日志”模式

日志总归会占用一些开销。EXT4允许关闭日志,以便某些有特殊需求的用户可以借此提升性能。

(11)默认启动Barrier

磁盘上配有内部缓存,以便重新调整批量数据的写操作顺序,优化写入性能,因此文件系统必须在日志数据写入磁盘之后才能写Commit记录。若Commit记录写入在先,而日志有可能损坏,那么就会影响数据完整性。EXT4文件系统默认启用Barrier,只有当Barrier之前的数据全部写入磁盘,才能写Barrier之后的数据。

(12)在线碎片整理

尽管延迟分配、多块分配和区段功能可以有效减少文件的碎片,但碎片还是不可避免会产生。EXT4支持在线碎片整理,并将提供e4defrag工具进行个别文件或整个文件系统的碎片整理。

(13)支持快速fsck

以前的文件系统版本执行fsck时很慢,因为它要检查所有的inode节点,而EXT4给每个块组的inode节点表中都添加了一份未使用inode节点的列表,所以EXT4文件系统做一致性检查时就可以跳过它们而只检查那些在使用的inode节点,从而提高了速度。

(14)支持纳秒级时间戳

EXT4之前的扩展文件系统的时间戳都是以秒为单位的,这已经能够应付大多数设置,但随着处理器的速度和集成程度(多核处理器)不断提升,以及Linux开始向其他应用领域发展,EXT4将时间戳的单位提升到纳秒。

EXT4给时间范围增加了两个位,从而让时间寿命再延长500年,EXT4的时间戳支持的日期达到2514年4月25日,而EXT3只达到2038年1月18日。 kxE/v/XvmpN8DDqjdPW1N8GQmoW4G/fI3ZTStJabbCbpTH2K3qTCitZZnJrmbA4l

点击中间区域
呼出菜单
上一章
目录
下一章
×