经典文件系统布局:超级块、位图与 ext4 日志
文件系统是磁盘上的元数据组织方案:超级块记录全局参数、位图跟踪空闲块与空闲 inode、inode 表存放文件元数据、数据区存放内容;ext4 在此之上用日志(journal)解决多块更新的原子性。
一句话定义
文件系统是磁盘上的元数据组织方案:超级块记录全局参数、位图跟踪空闲块与空闲 inode、inode 表存放文件元数据、数据区存放内容;ext4 在此之上用日志(journal)解决多块更新的原子性。
为什么重要
这是"把抽象落到扇区"的关键一跃:kp-021 讲 inode 是什么,本节讲 inode 们放在盘上哪里、坏了怎么发现、写一半断电怎么办。读懂布局图,就能读懂 fsck 在修什么、 dumpe2fs 在展示什么、以及 kp-024 崩溃一致性的全部前提。
前置知识
kp-021(inode 与目录项);kp-022(块与扇区)。
核心概念
- 超级块(superblock):文件系统身份证:总块数、块大小、inode 总数、挂载状态、特性标志。
- 位图(bitmap):每块一位/每 inode 一位的占用表,分配与释放的 O(1) 记账。
- 块组(block group):把盘切成多个自包含单元,各带自己的位图与 inode 表,让相关数据物理邻近。
- extent:ext4 的连续区间指针(起始块+长度),替代 ext2/3 的多级间接块。
- HTree 目录:大目录的哈希 B 树索引,避免线性扫描。
- 日志(journal):把元数据改动先顺序写入日志区再落盘原位,崩溃后可重放。
- VFS(虚拟文件系统):内核的统一接口层,ext4/XFS/btrfs 实现同一组操作表。
原理与机制
简化布局(经典 vsfs 模型,8 个块为例):
块: [0][1][2][3][4][5][6][7]
超S|i位图|d位图|i表|i表|数据|数据|数据
^S=超级块 ^inode表2块,每块4个inode ^数据块3个
读 /a.txt: 读超级块(已知位置) -> 读i位图/d位图找空闲 -> 读inode表[2]
-> 得数据块指针 -> 读数据[5]
创建文件: 位图标位(1个写) + inode 初始化(1个写) + 目录项写入(1个写)
-> 3+ 次离散写, 任何两次之间断电 = 元数据不一致 <-- 日志的动机
ext4 日志的三种模式:journal(数据+元数据都进日志,最安全最慢)、ordered(默认:先写数据、再提交元数据日志,折中)、writeback(只日志元数据,最快但崩溃后旧数据可能出现在新文件里)。日志提交流程:把事务写入日志区 → 写校验和提交记录 → checkpoint(把改动搬回原位)→ 日志区循环复用。因为日志写入是顺序的,它同时是 HDD 时代为数不多的"顺序化"收益点(呼应 kp-022)。
图示
创建文件的三处改动: 位图[1改成1] inode[新内容] 目录[新增项]
无日志: 任一处写后断电 -> 位图说占用/数据说空闲 等不一致 -> fsck 全盘扫描(小时级)
有日志: 改动先写日志 -> 提交点后崩溃 -> 挂载时重放日志 -> 秒级恢复
直观类比
超级块像商场的总导览图,位图像每个车位的占用指示灯,inode 表是商户登记簿,数据区是货架。日志像商场的施工日志本:今天所有改动先记在本子上,抄录到正式台账(checkpoint)之前断电,开业时照本子补抄一遍即可。
实例或案例
df -T # 各挂载点文件系统类型
dumpe2fs -h /dev/sda1 # 只读超级块摘要: 块大小/特性/日志模式
tune2fs -l /dev/sda1 | grep -i "block\|journal" # 元数据全景
debugfs -R "stat /etc/hostname" /dev/sda1 # 直接读某文件 inode(只读操作)
cat /proc/fs/ext4/sda1/options # 运行时日志选项(内核版本相关)
常见误区
- 认为 ext4 默认配置保证"数据不丢":默认
data=ordered只保证元数据一致,写入的数据仍可能丢,见 kp-024 的 fsync 语义。 - 把日志当备份:日志只覆盖崩溃窗口内的未完成事务,误删文件日志管不了。
- 认为 SSD 上日志纯亏:原子性与顺序写减少随机写放大,journal 依然是收益项。
与其他知识点的关系
崩溃窗口的细节展开为 kp-024;本节的"日志思想"在 kp-025 中长成 LSM 树与 COW 快照;VFS 统一接口连接 kp-026 的驱动模型。
延伸阅读
《操作系统导论》"File System Implementation"章(vsfs 完整推演);Rosenblum & Ousterhout 1991 LFS 论文(把"全部顺序写"推到极致的另一种答案)。
自测题
- 创建一个新文件至少要写哪几处元数据?
答:数据块位图(若写数据)、inode 位图标位、inode 初始化、父目录新增目录项——分散在盘上多处,故存在崩溃一致性问题。
- ext4 的 data=ordered 模式保证了什么、没保证什么?
答:保证崩溃后文件系统元数据自洽(无悬空块、无错配 inode);不保证用户数据在断电时已落盘,应用必须用 fsync 表达持久化意图。
- 为什么位图分配在 HDD 时代还要配合块组?
答:块组让一个文件的 inode、位图与数据物理邻近,既缩短寻道(kp-022)又降低位图锁争用,是空间局部性在盘上的布局化。