【Note】《深入理解Linux内核》 第十八章:深入理解 ext2 与 ext3 文件系统
《深入理解Linux内核》 第十八章:深入理解 ext2 与 ext3 文件系统
关键词:ext2、ext3、inode、超级块、块组、目录项、日志、文件块映射、文件系统挂载、文件系统操作接口、VFS挂钩
一、背景与简介
1.1 ext2 简介
ext2(第二扩展文件系统)是 Linux 长期使用的经典文件系统,拥有:
- 简单高效的设计;
- 灵活的元数据结构;
- 良好的性能。
ext2 由于不支持日志机制,在非正常断电情况下存在一致性问题。
1.2 ext3 简介
ext3 是 ext2 的直接扩展:
- 增加日志(journaling)功能;
- 提高文件系统一致性;
- 保持与 ext2 完全兼容(可以直接挂载为 ext2);
- 三种日志模式:journal、ordered(默认)、writeback。
二、磁盘结构布局
ext2/ext3 文件系统的磁盘结构分为若干块组(block group),每组包含以下信息:
Superblock
|
+-- Block Group Descriptors|+-- Block Bitmap+-- Inode Bitmap+-- Inode Table+-- Data Blocks
2.1 超级块(Superblock)
每个ext2/ext3文件系统都以一个超级块开始,包含整个文件系统的全局信息。
struct ext2_super_block {__u32 s_inodes_count;__u32 s_blocks_count;__u32 s_free_blocks_count;__u32 s_first_data_block;__u32 s_log_block_size;...
};
关键字段:
- 总 inode / block 数量;
- 空闲块/空闲 inode;
- 每块大小(通过 s_log_block_size 计算);
- 魔数验证(
0xEF53
);
2.2 块组描述符(Group Descriptor)
描述每个块组的结构布局:
struct ext2_group_desc {__u32 bg_block_bitmap;__u32 bg_inode_bitmap;__u32 bg_inode_table;__u16 bg_free_blocks_count;...
};
2.3 inode 表与数据块
每个块组有一个 inode 表(array of inodes)和 bitmap:
- inode bitmap:标记当前组中哪些 inode 被占用;
- block bitmap:标记数据块使用状态;
- inode table:真正的 inode 存储区;
- 数据块区:实际内容所在。
三、inode 与文件结构
3.1 inode 结构
每个文件或目录由一个 inode 表示:
struct ext2_inode {__u16 i_mode;__u16 i_uid;__u32 i_size;__u32 i_blocks;__u32 i_block[15]; // 数据块地址数组...
};
关键字段:
-
i_mode:文件类型与权限;
-
i_uid / i_gid:所有者信息;
-
i_size:文件大小;
-
i_block:最多可直接寻址12个块;
- i_block[12]:一级间接块;
- i_block[13]:二级间接;
- i_block[14]:三级间接;
3.2 文件内容寻址
基于 inode 中的 i_block[]
:
- 小文件(< 48KB):直接块(12个);
- 中等文件(48KB~4MB):一级间接;
- 大文件(4MB~数百MB):二级、三级间接;
- 使用块缓存+缓冲区头缓存加速访问。
四、目录实现
4.1 ext2 目录项结构
struct ext2_dir_entry {__u32 inode;__u16 rec_len;__u8 name_len;__u8 file_type;char name[EXT2_NAME_LEN];
};
说明:
- inode:文件 inode 编号;
- rec_len:目录项实际长度;
- name_len:文件名长度;
- name:实际文件名;
4.2 目录遍历机制
- 线性结构;
- 不排序;
- 查找复杂度 O(n);
- 新版(ext3/ext4)引入 HTree 改进目录查找效率。
五、ext3 日志机制(Journaling)
5.1 为什么需要日志
ext2 文件系统在写操作崩溃时可能导致元数据损坏,需要使用 fsck 工具修复,代价高昂。
ext3 通过将元数据写入日志区,再写入真实数据区,实现原子性。
5.2 ext3 日志格式
-
日志在文件系统中作为一个特殊 inode 管理;
-
日志项包括:
transaction ID
block number
commit records
-
日志使用循环缓冲结构。
5.3 日志模式
journal
:数据和元数据都写入日志;ordered
:先写数据再写元数据(默认);writeback
:无顺序保证,性能最高,安全性最低。
5.4 日志恢复
挂载文件系统时,ext3 会自动检查日志区域并进行回滚或提交。
六、挂载流程
ext3_fill_super()└── ext3_get_sb()└── mount_bdev()└── get_sb_bdev()└── fill_super()└── ext3_setup_super()
关键点:
- 检查超级块魔数;
- 分配 super_block/inode 结构;
- 初始化缓存;
- 挂载点结构挂接到 VFS。
七、VFS 与 ext2/ext3 接口挂钩
7.1 注册文件系统
register_filesystem(&ext3_fs_type);
ext3 提供以下方法集:
struct file_system_type ext3_fs_type = {.name = "ext3",.mount = ext3_mount,.kill_sb = kill_block_super,
};
7.2 inode 操作集
struct inode_operations ext3_dir_inode_operations = {.lookup = ext3_lookup,.create = ext3_create,.unlink = ext3_unlink,...
};
7.3 file_operations
针对普通文件:
struct file_operations ext3_file_operations = {.read_iter = generic_file_read_iter,.write_iter = generic_file_write_iter,.fsync = ext3_fsync,
};
八、性能与限制
8.1 ext2/ext3 的优点
- 简洁稳定;
- 支持大文件;
- 写入性能优秀;
- ext3 日志机制显著提升可靠性。
8.2 缺点
- 不支持延迟分配;
- inode 静态分配;
- ext2 无日志机制;
- ext3 不支持动态元数据扩展(如 inode 数目);
- ext3 性能与功能逐渐落后于 ext4、XFS、Btrfs。
九、调试与用户工具
tune2fs
:调整参数(日志模式等);fsck.ext2/ext3
:文件系统检查;dumpe2fs
:查看文件系统内部结构;debugfs
:文件系统调试工具;/proc/fs/ext3/
:内核态调试信息导出接口;
十、源码路径参考
路径 | 说明 |
---|---|
fs/ext2/ | ext2 文件系统实现 |
fs/ext3/ | ext3 文件系统实现 |
include/linux/ext2_fs.h | 结构定义(超级块、inode) |
fs/ext3/super.c | 挂载、卸载、日志挂钩 |
fs/ext3/inode.c | inode 读写、写回逻辑 |
fs/ext3/dir.c | 目录项处理 |
fs/ext3/balloc.c | 块分配逻辑 |
十一、小结
- ext2 是 Linux 的经典文件系统,设计简洁;
- ext3 在 ext2 基础上增加了日志机制;
- 块组结构设计优化了磁盘寻址;
- inode 结构支持多层间接寻址;
- ext3 的 ordered 模式在安全与性能之间取得良好平衡;
- 它们是理解 Linux 文件系统层与 VFS 协作的极好切入点。