技术编程|低调的 Linux 文件系统家族( 六 )


Linux Ext2 文件系统
现在我们一起看一下 Linux 中最流行的一个磁盘文件系统 , 那就是 ext2。 Linux 的第一个版本用于 MINIX1 文件系统 , 它的文件名大小被限制为最大 64 MB 。 MINIX 1 文件系统被永远的被它的扩展系统 ext 取代 , 因为 ext 允许更长的文件名和文件大小 。 由于 ext 的性能低下 , ext 被其替代者 ext2 取代 , ext2 目前仍在广泛使用 。
一个 ext2 Linux 磁盘分区包含了一个文件系统 , 这个文件系统的布局如下所示

技术编程|低调的 Linux 文件系统家族
本文插图

Boot 块也就是第 0 块不是让 Linux 使用的 , 而是用来加载和引导计算机启动代码的 。 在块 0 之后 , 磁盘分区被分成多个组 , 这些组与磁盘柱面边界所处的位置无关 。
第一个块是 超级块(superblock)。 它包含有关文件系统布局的信息 , 包括 i-node、磁盘块数量和以及空闲磁盘块列表的开始 。 下一个是 组描述符(group deor), 其中包含有关位图的位置 , 组中空闲块和 i-node 的数量以及组中的目录数量的信息 。 这些信息很重要 , 因为 ext2 会在磁盘上均匀分布目录 。
图中的两个位图用来记录空闲块和空闲 i-node , 这是从 MINIX 1文件系统继承的选择 , 大多数 UNIX 文件系统使用位图而不是空闲列表 。 每个位图的大小是一个块 。 如果一个块的大小是 1 KB , 那么就限制了块组的数量是 8192 个块和 8192 个 i-node 。 块的大小是一个严格的限制 , 块组的数量不固定 , 在 4KB 的块中 , 块组的数量增大四倍 。
在超级块之后分布的是 i-node 它们自己 , i-node 取值范围是 1 - 某些最大值 。 每个 i-node 是 128 字节的 long, 这些字节恰好能够描述一个文件 。 i-node 包含了统计信息(包含了 stat 系统调用能获得的所有者信息 , 实际上 stat 就是从 i-node 中读取信息的) , 以及足够的信息来查找保存文件数据的所有磁盘块 。
在 i-node 之后的是 数据块(data blocks)。 所有的文件和目录都保存在这 。 如果一个文件或者目录包含多个块 , 那么这些块在磁盘中的分布不一定是连续的 , 也有可能不连续 。 事实上 , 大文件块可能会被拆分成很多小块散布在整个磁盘上 。
对应于目录的 i-node 分散在整个磁盘组上 。 如果有足够的空间 , ext2 会把普通文件组织到与父目录相同的块组中 , 而把同一块上的数据文件组织成初始 i-node 节点 。 位图用来快速确定新文件系统数据的分配位置 。 在分配新的文件块时 , ext2 也会给该文件预分配许多额外的数据块 , 这样可以减少将来向文件写入数据时产生的文件碎片 。 这种策略在整个磁盘上实现了文件系统的 负载, 后续还有对文件碎片的排列和整理 , 而且性能也比较好 。
为了达到访问的目的 , 需要首先使用 Linux 系统调用 , 例如 open, 这个系统调用会确定打开文件的路径 。 路径分为两种 ,相对路径 和 绝对路径。 如果使用相对路径 , 那么就会从当前目录开始查找 , 否则就会从根目录进行查找 。
目录文件的文件名最高不能超过 255 个字符 , 它的分配如下图所示

技术编程|低调的 Linux 文件系统家族
本文插图

每一个目录都由整数个磁盘块组成 , 这样目录就可以整体的写入磁盘 。 在一个目录中 , 文件和子目录的目录项都是未经排序的 , 并且一个挨着一个 。 目录项不能跨越磁盘块 , 所以通常在每个磁盘块的尾部会有部分未使用的字节 。
上图中每个目录项都由四个固定长度的属性和一个长度可变的属性组成 。 第一个属性是 i-node 节点数量 , 文件 first 的 i-node 编号是 19, 文件 second 的编号是 42 , 目录 third 的 i-node 编号是 88 。 紧随其后的是 rec_len 域 , 表明目录项大小是多少字节 , 名称后面会有一些扩展 , 当名字以未知长度填充时 , 这个域被用来寻找下一个目录项 , 直至最后的未使用 。 这也是图中箭头的含义 。 紧随其后的是 类型域 :F 表示的是文件 , D 表示的是目录 , 最后是固定长度的文件名 , 上面的文件名的长度依次是 5、6、5 , 最后以文件名结束 。


推荐阅读