文件系统2:EXT

EXT主要有EXT2,EXT3,EXT4,主要介绍EXT2与EXT4。由于时间仓促,很多自己也不理解,可能有很多错误。

基本概念

首先介绍EXT中的基本概念:

  • 块:EXT用块管理分区空间,每一个块所占大小,常见的有1KB,2KB,4KB,8KB
  • 块组:几个块又被组成一个块组进行管理,一个块组含有的块的数量是块大小的8倍,因为块位图(之后介绍)占一个块,其中每一个比特对应一个块,所以如果一个块大小为1KB,那么一个块组有1K*8=8192个块

文件存储分配方式

在之前FAT文件系统中介绍文件的存储位置是通过FAT表和链接的方式来实现的,如下所示

而EXT采用的是节点表和索引式的方式来实现,即通过节点表将文件所占据的块记录下来,如下所示(当然实际不如下面这么简单,而且也不准确,只是说明这种思想,实际的更多细节可以看之后的内容)

其中节点表中一个文件的块的地址分为直接地址,一级索引,二级索引,三级索引,如下所示:

  • 直接地址即所指向的块保存的就是文件数据
  • 一级索引即所指向的块保存的是块的地址,如图中一级索引指向22号块,22号块中保存的是块的地址,其中指向的块有24,25等,而24指向的块才保存着文件的数据
  • 其它类型的索引类似

并不完全准确大致思想如下:

硬链接与软连接

在下面节点表会提到硬链接数,所以介绍一下。如下图所示,文件a,b,c都是图中最右上角的文件,但是b是采用硬链接的方式,直接指向了文件对应的节点4的地址,所以节点4的硬连接数为2。
而c采用软连接的方式,指向了一个保存最右上角的文件地址的文件,这类似于windows中的快捷方式。

EXT2

以每块占1KB为例,EXT2的结构如下所示:

  • 超块:包含重要的信息,包括文件系统中节点和块的总数和空闲的数量,每个块组中节点和块的数量等
  • 块组描述表GDT:定义所有块组的参数,包括块位图,节点位图,节点表的位置,空闲块,节点数量等
  • 超块备份和块组描述表备份:因为超块比较重要,所以起初,每个块组都保存一个超块和块组描述表的备份,但是会占用太多空间,所以改为只在组为0,1,3,5,7的幂的组才添加备份。
  • 块位图与节点位图之后介绍

注意:

  • 0号块不属于任何一个块组
  • 引导扇区始终占1024个字节,超块始终占1024个字节,又因为图中以每块占1KB为例,所以图中引导扇区占block0,超块占block1,但是如果每块占2KB,那么引导扇区和超块就会一起占block0。
  • 块组描述表在超块后的第一个块,可能不止占图中所示的一个块,可能占多个块

超块

偏移 意义
0-3 文件系统的节点总数,小于等于每组节点数*组数
4-7 文件系统的块总数,小于等于每组块数*组数
8-B 专门为超级用户保留的块的总数
C-F 所有空闲块的总数
10-13 所有空闲节点的总数
14-17 第一个块,也就是包含超块的ID,值为0或1
18-1B 块的大小,2^(10+值)
1C-1F 簇大小,2^(10+值)
20-23 每组的块数,最后一个组可能不够
24-27 每组簇数
28-2B 每组节点数,小于等于块大小除以节点大小。节点表占一个块,所以应该使节点表能够记录所有的节点,同时节点对应组中的块的数量,应该使节点数与块数达到一个平衡
2C-2F 文件系统被装入的最后时间
30-33 文件系统被访问的最后时间
34-35 文件系统被装入的次数
36-37 在验证文件系统前,可装入文件系统的最大次数
38-39 文件系统标识,EXT2为EF53
3A-3B 文件系统状态,如果为1,表示文件系统未被装入,为2,表示文件系统被装入
3C-3D 检测到错误时文件系统应该进行的操作
3E-3F 标识其版本的二级版本
40-43 最后一次文件系统检查时间
44-47 最多多长时间进行一次文件系统检查
48-4B 创建文件系统的操作系统的标识,0:linux,1:gnu hurd,2:masix,3:freebsd,4:lites
4C-4F 版本值,版本1具有可变的节点大小等特征
50-51 使用保留快的用户ID
52-53 使用保留块的用户组ID
54-57 用作标准文件(即不是目录等的普通文件)的第一个节点号,版本0的默认值为11,其它版本可以修改
58-59 节点的大小,在版本0中,值为128B,在其它版本中,值必须为2的幂次,且小于等于块的大小
5A-5B 超块所在组号
5C-5F 版本EXT2,3,4兼容的功能的掩码,文件系统支不支持都不影响,具体见文档
60-63 版本EXT2,3,4不兼容的功能的掩码,文件系统不支持就无法装入文件系统,具体见文档
64-67 只读功能掩码,如果掩码所示功能文件系统不支持,就以只读方式装入文件系统,具体见文档
68-77 卷ID,值唯一
78-87 卷名
88-C7 上次装入文件系统的目录路径
C8-CB 压缩算法
CC 创建文件时应预先分配的块数
CD 创建目录时应预先分配的块数
CE-CF 保留的描述表块数
D0-DF 包含日志超块的ID,EXT3中的日志功能
E0-E3 日志文件的索引节点号,EXT3中的日志功能
E4-E7 日志文件的索引号,EXT3中的日志功能
E8-EB 要删除的节点列表中的第一个节点,EXT3中的日志功能
EC-FB 4个32位的用于目录索引的哈希算法的种子
FC 默认用于目录索引的哈希算法版本
FD-FF 填充
100-103 默认文件系统装载选项
104-107 第一个元块组的块组ID
108-3FF 保留

本次以下面磁盘为例,其中主分区为EXT2

首先,找到磁盘MBR中分区表,得到主分区在磁盘2048扇区处,然后前1024B为引导扇区,这里引导扇区内容为空,之后2050扇区即为超块,如下所示

对应意义如下

偏移 意义
0-3 文件系统的节点总数为00 01 E6 50即124496
4-7 文件系统的块总数00 03 CC 00即248832
8-B 专门为超级用户保留的块的总数00 00 30 99即12441
C-F 所有空闲块的总数00 03 40 F5即213237
10-13 所有空闲节点的总数7E E5 01 00即124286
14-17 值为1,包含超块的块在块1中
20-23 每组的块数00 00 20 00即8192
24-27 每组簇数00 00 20 00即8192
28-2B 每组节点数B0 0F 00 00即4016
38-39 文件系统标识EF 53为EXT2
4C-4F 修订版本值00 00 00 01即版本为1
54-57 用作标准文件(即不是目录等的普通文件)的第一个节点号00 00 00 0B即为11
58-59 节点的大小00 80即128B
5A-5B 超块所在组号00 00即块组0

块组描述表

块组描述表表示文件系统中所有块组的信息,其中每32个字节表示一个块组的信息,这32个字节的结构信息如下

偏移 意义
0-3 该组块中的块位图的第一个块号
4-7 该组块中的节点位图的第一个块号
8-B 该组块中的节点表的第一个块号
C-D 该组块中空闲块总数
E-F 该组块的空闲节点总数
10-11 该组分配给目录的节点数
12-1F 保留填充

超块的下一个块为块组描述表,这里一个块是1024B,就是两个扇区,而超块在2050扇区,所以块组描述表在2052扇区,以下为块组描述表的部分数据

只看第一个块组也就是块组0的信息,即前32位

偏移 意义
0-3 该组块中的块位图的第一个块号00 00 00 03即3,也就是该组块中的块位图在块3
4-7 该组块中的节点位图的第一个块号00 00 00 04即4,也就是该组块中的节点位图在块4
8-B 该组块中的节点表的第一个块号00 00 00 05即5,也就是该组块中的节点表是从块5开始的
C-D 该组块中空闲块总数0A B1,即2737
E-F 该组块的空闲节点总数0F 9D即3997
10-11 该组分配给目录的节点数00 02即2

块位图

每一位表示一个块是否被使用,1表示已用,0表示未用,第一个块(编号为0)由0字节的0位表示,第九个块由1字节的0位表示。块3中的块位图如下

节点位图

每一位表示一个节点是否被使用,编号从1开始,所以第一个节点(编号为1)由0字节的0位表示。保留的节点在初始化时都会被标记为已使用(前几个节点是被保留的,版本0为11节点,其它版本要看设置为多少,在超块的偏移54-57处已经确定)。块4中的节点位图如下

节点表

节点表保存了各种各样文件的位置,大小,类型和访问权限,但不保存文件名,文件名只保存在目录中。节点表中每128B表示一个节点项,节点表中前几个项是被保留的(版本0为11个项,其它版本要看设置为多少,在超块的偏移54-57已经确定,这11个中第1个是用作坏块的节点,第2个:根目录节点,第3,4个:根访问控制相关,第5:引导加载程序节点,第6:未删除目录节点)。每一个节点项结构如下:

偏移 意义
0-1 该文件的格式和访问权限,各值的含义见下图,该偏移处的值可以是下图中任意值的组合

偏移 意义
2-3 与文件关联的用户ID
4-7 版本0中这32位(有符号的)表示文件的大小(单位为字节),在其它版本表示文件大小的低32位
8-B 上次访问该节点的时间(从1970.1.1以来的秒数)
C-F 创建节点的时间(从1970.1.1以来的秒数)
10-13 上次修改节点的时间(从1970.1.1以来的秒数)
14-17 删除节点的时间(从1970.1.1以来的秒数)
18-19 有权访问此文件的用户组
1A-1B 该节点的硬链接数
1C-1F 保留的用于包含此节点数据的512B的块的总数
20-23 访问此节点时EXT2的行为,如下图,其中如果值为EXT2_INDEX_FL,表示这个节点指向目录,且目录时索引格式


偏移 意义
24-27 与操作系统相关的值
28-63 每32位为一个块号,共15个块。前12个是直接地址,第13个是一级索引,14,15类推
64-67 文件版本
68-6B 包含扩展属性的块编号,版本0的块是没有扩展属性的,所以值为0
6C-6F 版本0的此值始终为0,其它版本表示文件大小的高32位
70-73 文件段的位置
74-7F 操作系统的相关结构,具体见文档

块5中的节点表如下:
前11个为保留的节点,所以以下是节点表中保留的项的部分数据。

其中第二个节点,也就是根目录节点分析如下:

偏移 意义
0-1 该文件的格式和访问权限ED 41,即对照上图中的值可以确定其为drwxr-xr-x,分析ED 41小端存储,实际为41 ED,对照表中4000为目录,所以为d,表中100为用户可读,所以为r,表中用户可写,用户可执行,组可读为80,40,20,加起来为E0,所以为wxr,表中用户可执行,其他人可读,其他人可执行为8,4,1,加起来为D,综合起来确定了该文件的属性
2-3 与文件关联的用户ID00 00
4-7 因为在前面知道是版本1,所以表示文件大小的低32位00 00 00 04
18-19 有权访问此文件的用户组00 00
1A-1B 该节点的硬链接数00 04即4
1C-1F 保留的用于包含此节点数据的512B的块的总数00 00 00 02即2
28-63 只有一个包含节点数据的块的块号00 00 FB 01即507
6C-6F 文件大小的高32位00 00 00 00,综合低位的00 00 00 04知文件4B大小

目录

目录有其特定的格式。目录分为链目录格式与索引目录格式,在文件多的时候索引目录格式查找文件更快,在节点表的偏移20-23处表明了格式。

链表目录格式

偏移 意义
0-3 文件的节点号,如果值为零,表示这一项没有被使用
4-5 从当前目录项的开头到下一个目录项的16位无符号移位,即目录项的长度。此字段的值必须至少等于当前项的长度。目录项必须在4字节边界上对齐,并且不能有任何跨越多个数据块的目录项。如果一个项不能完全放入一个数据块,则必须将其推送到下一个数据块,并正确调整前一条项的记录。
6 文件名多少字节的长度
7 文件类型,0:不明类型,1:常规文件,2:目录,3:字符设备,4:块设备,5:缓存文件,6:套接字文件,7:链接文件
8-(取决于文件名长度和边界对其的要求) 文件名

结合例子介绍,在上面的节点表中我们知道一个目录在507块,也就是在扇区2048+507*2=3062,其中2048是分区的起始扇区(其实2048-2049为块0,而507块是块本身,所以扇区为2050+2*(507-1)),其数据如下

开始为当前目录项

偏移 意义
0-3 文件节点号为2,由上可知,该目录确实存在2节点
4-5 目录项的长度为12
6 文件包1B长
7 值为2表示为目录
8-B 文件名为.

下一项为其父目录项,由上知前一项录项长度为12,所以下一项从偏移C处开始

偏移 意义
0-3 文件节点号为2
4-5 目录项的长度为12
6 文件名2B长
7 值为2表示目录
8-B 文件名为..

其余项就是该目录下的文件的项了

索引目录格式

使用哈希树来组织和查找目录项。为了与链表目录格式兼容,在前面一块放置一个链表目录格式的数据块,下一个数据块才为索引目录格式块。当索引目录项超过一个数据块可容纳的数时,将创建间接索引,即分配给该目录另一个数据块。关于此格式的更多原理见文档

首先是索引根目录项结构

偏移 意义
0-3 当前目录节点
4-5 当前项长度
6 名字长度,单位B
7 文件类型,为2,也就是目录类型
8 文件名.
9-B 填充
C-F 当前目录节点
10-11 当前项长度
12 名字长度,单位B
13 文件类型,为2,也就是目录类型
14-15 文件名..
16-17 填充
18-1B 保留
1C 哈希版本
1D 索引目录信息长度,这里索引目录信息就是偏移18-1F的值
1E 索引目录间接索引数
1F 保留

之后是索引目录项,第一个索引目录项如下:

偏移 意义
0-1 块中所能容纳索引目录项的最大数量
2-3 现在已容纳的索引目录项的数量

之后的索引目录项结构如下

偏移 意义
0-3 目录名的哈希值
4-7 目录节点的块号

EXT4

相比于EXT2,在EXT4中可以将几个块组作为一个逻辑块组绑定在一起,称为元块组,其它块组的节点位图,块位图都可以统一放在一起。以下主要介绍EXT4中格式与EXT2不一样的地方

超块

与EXT2相比在以下偏移处不同

偏移 意义
FD 不明白
FE-FF 块组描述符的大小
100-103 默认文件系统装载选项,详细见文档
104-107 第一个元块组的块组ID
108-10B 文件系统创建时间(从1970.1.1以来的秒数)
10C-14F 日志节点的备份
150-153 块总数的高32位
154-157 保留的块数的高32位
158-15B 空闲的块数的高32位
15C-15D 节点(因为对节点进行了扩展)额外至少有多少字节
15E-15F 节点额外应该保留多少字节
160-163 标志,是这些的组合,0001:使用签名哈希目录,0002:使用未签名哈希目录,0004:测试代码
164-165 移动到读取下一个磁盘之前从磁盘读取或写入磁盘的逻辑块数
166-167 防止文件系统多次挂载
168-169 多挂载保护数据的块编号
170-173 返回到当前磁盘之前从磁盘读取或写入磁盘的逻辑块数
174 元数组的大小,值为2^该值
175 元数据校验和算法类型,值为1指crc32c算法
176-177 保留
178-17F 文件系统运行期间,写入的KB数
180-183 活动快照的节点号
184-187 活动快照的序列ID
188-189 为活动快照将来使用而保留的块数
190-193 磁盘快照列表的头的块号
194-197 错误数
198-19B 第一次发生错误的时间(从1970.1.1以来的秒数)
19C-19F 第一次错误涉及的节点
1A0-1A7 第一次错误涉及的块数
1A8-1C7 发生错误的函数名字
1C8-1CB 发生错误的行号
1CC-1CF 最近错误的时间(从1970.1.1以来的秒数)
1D0-1D3 最近错误涉及的节点
1D4-1D7 最近错误的行号
1D8-1DF 最近错误涉及的块数
1E0-1EF 最近错误的函数名字
200-23F ASCIIZ挂载选项字符串
240-243 用户配额文件的节点数
244-247 组配额文件的节点数
248-24B 文件系统中开销块或簇
24C-253 包含超块备份的块组,每32位为一组
254-257 使用的加密算法,0:不使用,1:XTS的256b的AES,2:GCM的256b的AES,3:CBC的256b的AES
258-267 用于加密的string2key算法的盐值
268-26B lost+found文件的节点数
26C-26F Inode that tracks project quotas
270-273 用于元数据校验和计算的种子,值为crc32c
274-3FB 保留
3FC-3FF 超块校验和

本次以下面磁盘为例,其中root为EXT4

首先在偏移1024B处找到超块,如下所示,这里就不一一分析了,直接使用软件自动分析。
在偏移18处可以看到块的大小,为2^(10+2),即4K

块组描述表

块组描述表中每一项与EXT2相比,有32B版本和64B版本,32B是EXT2中的扩展

偏移 意义
0-3 块位图的低32位
4-7 节点位图的低32位
8-B 节点表的低32位
C-D 空闲块数的低32位
E-F 空闲节点的低32位
10-11 目录数量的低32位
12-13 块组标志,这些值的任意组合,1:节点表和位图未初始化,2:块位图未初始化,4:节点表被清零
14-17 快照位图的低32位
18-19 块位图校验和的低32位
1A-1B 节点位图校验和的低32位
1C-1D 未使用的节点数的低32位
1E-1F 组描述符校验和

以上为32B版本,64B版本加上下面的内容

偏移 意义
20-23 块位图的高32位
24-27 节点位图的高32位
28-2B 节点表的高32位
2C-2D 空闲块数的高32位
2E-2F 空闲节点的高32位
30-31 目录数量的高32位
32-33 未使用的节点数的高32位
34-37 快照位图的高32位
38-39 块位图校验和的高32位
3A-3B 节点位图校验和的高32位
3C-3F 保留

由超块知一个块占4K,所以块组描述符在扇区8,即超块的下一块中。这里只看第一个块组项,可知该块组的块位图在1025*8(因为一个块4K,占8个扇区)处,节点位图在1041*8处,节点表在1057*8处。

节点表

相比于EXT2,增加了如下字段

偏移 意义
80-81 节点大小(超出原始128B的部分),在ext2和ext3中节点大小为128B,超出的部分记录在这个字段
82-83 节点校验和的高16位
84-87 额外的更改时间
88-8B 额外的修改时间
8C-8F 额外的访问时间
90-93 文件创建时间
94-97 额外的文件创建时间
98-9B 版本号的高32位
9C-9F 项目ID

extent tree

并且在偏移28-63处不再使用直接地址,一级索引这样的方式找块号(在EXT2和EXT3中使用),而改用扩展树extent tree结构,其结构如下,偏移为偏移28-63处内部的相对偏移,开始12个字节为树结构的头

偏移 意义
0-1 标记,为F3 0A
2-3 树头后的有效项数
4-5 树头后面可以有的最大项数
6-7 树的深度,最大为5,为0则表明,每一项直接指向数据块
8-B 树的生成

树头之后,跟着每一项,每一项的结构如下

偏移 意义
0-3 该树覆盖的范围中第一个文件的块号
4-5 树覆盖的范围所占总块数
6-7 此项指向的块号的高16位
8-B 此项指向的块号的低32位

大致结构示意如下
img

日志

为了防止系统崩溃导致数据前后不一致,从EXT3引入日志系统,都按大端存储

在超块中可以知道日志节点在8号节点(11个保留节点中从0开始编号,但是第0个不存在,所以8号实际上还是第8个节点)。
通过块组描述表知道节点表在1057*8处。
在节点表,找到第8个节点,如下图所示红框处。
在第8个节点,通过extent tree的结构中第一项8-B偏移处的块号的低32位(红线处),知道日志在2129920块处,即2129920*8扇区处

日志数据如下

其结构为:

日志中每一个块都有一个12字节的开头

偏移 意义
0-3 日志标记,值为C03B3998
4-7 块内容的描述,1:描述符,表示块位于事务提交之前,2:块阻止记录,表示块事务提交完成,3:日志超块v1,4:日志超块v2,5:阻止重写记录,使得日志能够跳过后面重写的块
8-B 块对应的事务ID

日志超块

偏移 意义
0-B 固定的块头
C-F 日志块的大小
10-13 日志中块的总数
14-17 日志的第一个块
18-1B 日志中预期的第一个提交ID
1C-1F 日志开始的块编号
20-23 错误值
24-27 日志兼容功能,见文档
28-2B 日志不兼容功能,见文档
2C-2F
30-3F 日志的128位uuid
40-43 共享此日志的文件系统数
44-47
48-4B
4C-4F
50 用于日志的校验和算法,1:CRC32,2:MD5,3:SHA1,4:CRC32C
51-53 填充
54-57 日志中快速提交块数
58-FB 填充
FC-FF 整个超块的校验和,值设为0
100-3FF 共享日志的所有文件系统ID

描述符块

开始依然是固定的12B块头,之后是多个日志块的标记,如果日志超块中偏移28-2B处设置了值为0x10的JBD2_FEATURE_INCOMPAT_CSUM_V3,则格式如下,偏移为这些内容的相对偏移

偏移 意义
0-3 数据块在磁盘上位置的低32位
4-7 描述符块对应的标记,见文档
8-B 数据块在磁盘上位置的高32位
C-F 日志UUID,序列号和数据块的校验和
10-1F 该标记的uuid

如果没有设置,则格式如下,偏移为这些内容的相对偏移

偏移 意义
0-3 数据块在磁盘上位置的低32位
4-5 日志UUID,序列号和数据块的校验和的低16位
6-7 描述符块对应的标记,见文档
8-B 数据块在磁盘上位置的高32位,当日志超块表明为64位版本时,字段才存在
C-1F 该标记的uuid

参考

https://www.nongnu.org/ext2-doc/ext2.pdf
https://www.kernel.org/doc/html/latest/filesystems/ext4/about.html
http://web.mit.edu/tytso/www/linux/ext2intro.html
https://students.mimuw.edu.pl/ZSO/Wyklady/11_extXfs/extXfs.pdf
https://zhuanlan.zhihu.com/p/61749046
https://www.cnblogs.com/ggjucheng/archive/2012/08/22/2651641.html
https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Hash_Tree_Directories

posted @ 2022-04-22 20:23  启林O_o  阅读(282)  评论(0编辑  收藏  举报