
数据恢复专题:学习 Ext3 文件系统的 i-节点、目录项结构(17)
前言
本篇将对 Ext3 文件系统的 i-节点、目录项进行分析。
知识点总览
-
Ext3 文件系统 i-节点分析
-
Ext3 文件系统目录项分析
Ext3 文件系统 i-节点分析
Ext3 文件系统的 i-节点用来存储跟文件相关的除文件名以外的所有信息,i-节点被存储在 i-节点表中,i-节点表的位置在 i-节点位图后。

i-节点存储的信息包括指向文件的链接数、文件大小、文件的时间信息、文件所属的用户 ID、文件所属的组 ID、文件内容存放地址的块指针等,这些重要信息也被称为元数据。
i-节点的结构特点如下:
-
Ext3 文件系统的每个块组中都有一个自己的 i-节点表。i-节点表由很多 i-节点组成,每个文件或者目录使用一个 i-节点。
-
i-节点表起始于 i-节点位图所在块的下一个块。
- 超级块中记录着文件系统的 i-节点总数和每块组包含的 i-节点数。
- 每个 i-节点的基本大小为 128 字节,但当超级块中 4CH ~ 4FH 偏移处的“主版本号”被定义为“动态”时,i-节点的实际大小由超级块的 58H ~ 59H 处定义,i-节点可以被定义为大于 128 字节的“大 i-节点”。
-
每个 i-节点都有一个编号,第一个 i-节点的编号为 1。
-
1 ~ 10 号 i-节点被系统保留,所以在超级块中会描述第一个非保留的 i-节点,这个值一般是 11。
-
前 10 个保留的 i-节点在 i-节点位图中被标示为已分配,其中 1 号 i-节点一般用于描述坏块;2 号 i-节点被分配给根目录使用;8 号 i-节点通常用于描述日志。
-
如果已知一个 i-节点号,就可以计算出该 i-节点所在块组,计算方法为
(i-节点号 −1)/ 每块组 i-节点数
Ext3 文件系统的 i-节点结构分析

| 字节偏移 | 字段长度 (字节) | 字段名和定义 |
|---|---|---|
| 0x00~0x01 | 2 | 文件模式 |
| 0x02~0x03 | 2 | 用户 UID 的低 16 位 |
| 0x04~0x07 | 4 | 字节数的低 32 位 |
| 0x08~0x0B | 4 | 最后访问时间 |
| 0x0C~0x0F | 4 | i-节点变化时间 |
| 0x10~0x13 | 4 | 最后修改时间 |
| 0x14~0x17 | 4 | 删除时间 |
| 0x18~0x19 | 2 | 组 ID 的低 16 位 |
| 0x1A~0x1B | 2 | 硬链接数 |
| 0x1C~0x1F | 4 | 文件所占扇区数(512 字节/块) |
| 0x20~0x23 | 4 | Flag |
| 0x24~0x27 | 4 | 未用 |
| 0x28~0x2B | 4 | 第 1 个直接块指针 |
| 0x2C~0x2F | 4 | 第 2 个直接块指针 |
| 0x30~0x33 | 4 | 第 3 个直接块指针 |
| 0x34~0x37 | 4 | 第 4 个直接块指针 |
| 0x38~0x3B | 4 | 第 5 个直接块指针 |
| 0x3C~0x3F | 4 | 第 6 个直接块指针 |
| 0x40~0x43 | 4 | 第 7 个直接块指针 |
| 0x44~0x47 | 4 | 第 8 个直接块指针 |
| 0x48~0x4B | 4 | 第 9 个直接块指针 |
| 0x4C~0x4F | 4 | 第 10 个直接块指针 |
| 0x50~0x53 | 4 | 第 11 个直接块指针 |
| 0x54~0x57 | 4 | 第 12 个直接块指针 |
| 0x58~0x5B | 4 | 间接块指针 |
| 0x5C~0x5F | 4 | 二级间接块指针 |
| 0x60~0x63 | 4 | 三级间接块指针 |
| 0x64~0x67 | 4 | 文件版本号(用于 NFS) |
| 0x68~0x6B | + | 扩展属性块的低 32 位 |
| 0x6C~0x6F | 4 | 字节数的高 32 位 |
| 0x70~0x73 | 4 | 片段的数据块地址 |
| 0x74 | 1 | 片段索引 |
| 0x75 | 1 | 段大小 |
| 0x76~0x77 | 2 | 未用 |
| 0x78~0x79 | 2 | UID 的高 16 位 |
| 0x7A~0x7B | 2 | GID 的高 16 位 |
| 0x7C~0x7F | 4 | 未用 |
Ext3 Inode 的结构具体解析
-
0x00~0x01: 文件模式
展开/收起 文件模式(i_mode)的解析
“文件模式”参数占用两个字节,按照其对应的 16 位二进制分成三组:
-
第一组为 0 ~ 8 位,描述权限标志
16 位的“文件模式”参数中 0 ~ 8 位用来描述用户的权限。
Linux 的用户被分成三类,即
属主、同组用户和其他用户。属主是指 i-节点中记录的用户 ID 的所有者;
组用户以 i-节点中的组 ID 进行区分;
其他用户为除属主、同组用户以外的所有用户。
用户的权限分为
读、写和执行三种 -
第二组为 9 ~ 11 位,用来定义可执行文件和目录
16 位的“文件模式”参数中 9 ~ 11 位用来定义可执行文件和目录。
这三个位设置的值不同:
如果是可执行文件,其执行方式就会有所不同;
如果是目录,则该目录中的文件会具有特定的属性
-
第三组为 12 ~ 15 位,描述文件类型。
16 位的“文件模式”参数中 12 ~ 15 位用来定义文件类型
文件类型的各种值只能单独使用(互斥),不能同时将几个值组合起来使用。
以下为文件模式(
i_mode)值的组合:
-
| 值 | 描述 |
|---|---|
| 0x1 | S_IXOTH(其他人可执行) |
| 0x2 | S_IWOTH(其他人可写) |
| 0x4 | S_IROTH(其他人可读) |
| 0x8 | S_IXGRP(组成员可执行) |
| 0x10 | S_IWGRP(组成员可写) |
| 0x20 | S_IRGRP(组成员可读) |
| 0x40 | S_IXUSR(所有者可执行) |
| 0x80 | S_IWUSR(所有者可写) |
| 0x100 | S_IRUSR(所有者可读) |
| 0x200 | S_ISVTX(粘接位) |
| 0x400 | S_ISGID(设置 GID) |
| 0x800 | S_ISUID(设置 UID) |
| 这些是互斥的文件类型: | |
| 0x1000 | S_IFIFO(先进先出(管道)) |
| 0x2000 | S_IFCHR(字符设备(裸设备)) |
| 0x4000 | S_IFDIR(目录) |
| 0x6000 | S_IFBLK(块设备) |
| 0x8000 | S_IFREG(正常文件) |
| 0xA000 | S_IFLNK(符号链接) |
| 0xC000 | S_IFSOCK(套接字) |
“先进先出”也称为管道,用于两个进程间的数据传送。一个进程可以打开文件接收信息,但这些信息必须是由另一个进程写入的,在这个过程中数据存储在内存中而不是在磁盘上。
“字符设备”也称为裸设备,用于不需要一次读取一个数据块的设备,如键盘。也可以给块设备设置字符设备属性,但在不以块大小为读取和写入单位时会产生错误。i-节点通常会保存某些信息用以说明哪些块已经分配给记录设备标识符的文件。
“块设备”用于只能以块大小为单位进行读取操作的设备,如硬盘。从硬盘读取数据时,一次至少要读取 512 个字节,即 1 个扇区。如果一个程序要从块设备中读取少于 1 个扇区的数据,操作系统也需要读取 1 个扇区,然后只把需要的数据返回给程序。
“动态链接”是一种指向其他文件或目录的特殊文件,它的“内容”是所指向的目标文件的内容。动态链接其实就是文件或目录的快捷方式。
“套接字”用于进程间的双向通信,如命名管道,这些数据并不写入磁盘。
</details>
2. 0x02~0x03: 用户 UID 的低 16 位
-
0x04~0x07: 字节数的低 32 位
如果该 i-节点是一个文件的 i-节点,则“总字节数”是指文件的大小;如果该 i-节点是一个目录的 i-节点,则“总字节数”是指该目录的下级目录区的大小。
在 Ext 及 Ext2 文件系统中,用 32 位来描述“总字节数”这个参数,能够管理的文件大小最大为 4GB;从 Ext3 开始,文件系统能够支持大文件,也就是用 64 位存储“总字节数”这个参数,该位置为低 32 位,高 32 位在 0x6C ~ 0x6F 偏移处描述。
-
0x08~0x0B: 最后访问时间
-
0x0C~0x0F: i-节点变化时间
-
0x10~0x13: 最后修改时间
-
0x14~0x17: 删除时间
Ext3 的 i-节点中描述了四个时间信息,包括最后访问时间、i-节点变化时间、最后修改时间及删除时间。
提示:当新建立一个文件时,最后访问时间、i-节点变化时间、最后修改时间这三个时间值都被设置为文件创建时的当前时间,删除时间则不设置,只有在文件被删除时,才设置文件的删除时间。
-
0x18~0x19: 组 ID 的低 16 位
-
0x1A~0x1B: 硬链接数
-
0x1C~0x1F: 文件所占扇区数(512 字节/块)
-
0x20~0x23: Flag。用来定义文件的属性
Flag值的组合
| 值 | 描述 |
|---|---|
| 0x1 | 此文件需要安全删除 (EXT4_SECRM_FL) (未实现) |
| 0x2 | 文件需要被保护,阻止删除操作 (EXT4_UNRM_FL) (未实现) |
| 0x4 | 文件已经被压缩 (EXT4_COMPR_FL) (未真正实现) |
| 0x8 | 对文件的所有写操作必须是同步的 (EXT4_SYNC_FL) |
| 0x10 | 文件是不可变的 (EXT4_IMMUTABLE_FL) |
| 0x20 | 文件只能被追加 (EXT4_APPEND_FL) |
| 0x40 | dump(1) 工具不应该转储这个文件 (EXT4_NODUMP_FL) |
| 0x80 | 不更新访问时间 (EXT4_NOATIME_FL) |
| 0x100 | 脏压缩文件 (EXT4_DIRTY_FL) (未使用) |
| 0x200 | 文件具有一个或多个压缩群集 (EXT4_COMPRBLK_FL) (未使用) |
| 0x400 | 文件不能被压缩 (EXT4_NOCOMPR_FL) (未使用) |
| 0x800 | 加密的 i-节点 (EXT4_ENCRYPT_FL) 此位值以前是 EXT4_ECOMPR_FL (压缩错误),从未使用过 |
| 0x1000 | 目录具有散列索引 (EXT4_INDEX_FL) |
| 0x2000 | AFS 魔术目录 (EXT4_IMAGIC_FL) |
| 0x4000 | 文件数据必须始终通过日志写入 (EXT4_JOURNAL_DATA_FL) |
| 0x8000 | 不应合并文件尾部 (EXT4_NOTAIL_FL) (分机 4 未使用) |
| 0x10000 | 所有目录条目数据应同步写入 (EXT4_DIRSYNC_FL) |
| 0x20000 | 目录层次结构的顶部 (EXT4_TOPDIR_FL) |
| 0x40000 | 此文件的大小非常大 (EXT4_HUGE_FILE_FL) |
| 0x80000 | i-节点使用扩展数据块 (EXT4_EXTENTS_FL) |
| 0x100000 | 文件受验证保护 (EXT4_VERITY_FL) |
| 0x200000 | Inode 在其数据块中存储大型扩展属性值 (EXT4_EA_INODE_FL) |
| 0x400000 | 此文件具有在 EOF 之后分配的块 (EXT4_EOFBLOCKS_FL) (已弃用) |
| 0x01000000 | i-节点是一个快照 (EXT4_SNAPFILE_FL) (不在主线中) |
| 0x04000000 | 正在删除快照 (EXT4_SNAPFILE_DELETED_FL) (不在主线中) |
| 0x08000000 | 快照收缩已完成 (EXT4_SNAPFILE_SHRUNK_FL) (不在主线中) |
| 0x10000000 | i-节点具有内联数据 (EXT4_INLINE_DATA_FL) |
| 0x20000000 | 创建具有相同项目 ID 的子项 (EXT4_PROJINHERIT_FL) |
| 0x80000000 | 保留给 ext4 库 (EXT4_RESERVED_FL) |
| 聚合标志: | |
| 0x705BDFFF | 用户可见的 Flag |
| 0x604BC0FF | 用户可修改的 Flag |
</details>
12. 0x24~0x27: 未用
-
0x28~0x63: 块指针
在 ext3 的块指针中,其中前 12 项直接保存了块的位置,也就是说,我们可以通过 i_block[0-11],直接得到保存文件内容的块
如果文件大于 12 个块,则第 13 个块指针是一个间接块指针,它指向的块内存放的是直接块指针而不是文件内容。
如果间接块指针指向的块依然存放不下文件所占的块号,就需要二级间接块指针了。第 14 个块指针是二级间接块指针,它指向的块内存放的是一级间接块指针而不是文件内容。
二级间接块指针如果还是无法满足文件的块号需求,就要用第 15 个块指针了。这是三级间接块指针,它指向的块内存放的是二级间接块指针而不是文件内容。

-
0x64~0x67: 文件版本号(用于 NFS)
-
0x68~0x6B: 扩展属性块的低 32 位
该字段中可能有许多种扩展属性,ACL 是其中之一
-
0x6C~0x6F: 字节数的高 32 位
-
0x70~0x73: 片段的数据块地址
-
0x74 : 片段索引
-
0x75 : 段大小
-
0x76~0x77: 未用
-
0x78~0x79: UID 的高 16 位
-
0x7A~0x7B: GID 的高 16 位
-
0x7C~0x7F: 未用
Ext3 文件系统目录项分析
目录项用来存放文件及目录的 i-节点号、目录项的长度、文件名等信息,它们存储在分配给目录的块中
Ext3 文件系统目录项的结构分析

上图文件名中的绿色标记为文件名补位部分,不计入“文件名长度”项中
| 字节偏移 | 字段长度(字节) | 字段名和定义 |
|---|---|---|
| 0x00 ~ 0x03 | 4 | i-节点号 |
| 0x04 ~ 0x05 | 2 | 目录项长度 |
| 0x06 ~ 0x06 | 1 | 文件名长度 |
| 0x07 ~ 0x07 | 1 | 文件类型 |
| 0x08 ~ | 变长 | 文件名 |
目录项中“文件类型”的具体分类
| 类型值 | 类型含义 |
|---|---|
| 0x01 | 文件 |
| 0x02 | 目录 |
| 0x07 | 符号链接 |
目录项结构特点
Ext3 文件系统的目录项有如下特点:
-
目录项存储在目录区中,i-节点内有描述目录区地址的块指针。
-
目录项的长度不是固定的,其长度随着文件名长度的不同而不同,文件名最长为 255 个字符,并且使用 ASCII 码进行存储。
-
Ext3 的目录项长度虽然不固定,但一定是 4 字节的倍数,每个目录项以 4 字节为边界进行排列,即每个目录项的起始字节必须是位于目录内可被 4 整除的相对偏移字节处。
-
另外,Ext3 目录项的结束位置如果没有达到 4 字节的边界,那么也需要在文件名后加空字节以达到 4 字节的边界。
-
目录区中的前两个目录项一定是“.”和“. .”目录,“.”目录表示当前目录,“. .”目录表示父目录。
-
每个目录项中有一个长度值指向下一个目录项,最后一个目录项的长度则指向本块的结尾处
评论
评论加载中…