Skip to content

第八十七章:ext4 之基

斩灵期

涉及内核源码:

林小源在森林深处发现了一棵巨树。

这棵树比周围的古树都要粗壮——树干的直径足有十丈,树皮上的纹路深如沟壑。树干上刻着"ext4"三个字,字迹苍劲有力,像是被闪电劈出来的。

"你就是 ext4?"林小源仰头问道。

巨树发出一声低沉的笑,声音像远处的雷鸣:"我是这片森林的主人。Linux 世界里,七成以上的文件系统都是我的子民。"

林小源走近树干,伸手触摸。树皮粗糙,每一道纹路都是一条信息。他闭上眼睛,神识渗入树干内部——眼前的景象让他屏住了呼吸。

树干内部不是实心的,而是一个精密的分区结构。最外面是一层薄薄的"Boot Block",只有 1KB。里面是一个个整齐排列的方阵,每个方阵就是一个"Block Group"。

"每个 Block Group 里有什么?"他问。

"Superblock 的备份,"巨树说,"Group Descriptors、Block Bitmap、Inode Bitmap、Inode Table、Data Blocks。一个方阵就是一个小王国——有自己的 superblock 副本,自己的 bitmap,自己的数据区。"

林小源看到 Block Bitmap 上无数个亮点,每个亮点代表一个数据块。有的亮着——已分配;有的暗着——空闲。

"这就是磁盘布局,"他低声说。

"对,"巨树说,"ext4 的磁盘被分成无数个 Block Group。每个 Group 独立管理自己的空间。坏了一个 Group,其他的不受影响。"

林小源在巨树的树干上发现了一道裂缝。

裂缝里面露出一个奇特的结构——不是传统的间接块指针,而是一个紧凑的树形结构,树的每个节点都记录着"起始块号""长度""偏移"。

"这是 extent,"巨树说,声音带着一丝骄傲,"ext4 的杀手锏。"

"和传统的间接块有什么区别?"

"间接块是这样的,"巨树说,"一个 inode 里有 12 个直接块指针,一个间接块指针,一个二级间接块指针,一个三级间接块指针。要找第 1000 个块,你得先读间接块,再读二级间接块——两层跳转。"

"extent 呢?"

"extent 说:'从第 100 块开始,连续 500 块都是我的。'一个 extent 结构就能描述连续的数据块。大文件只需要几个 extent,不需要几百个间接块指针。"

林小源恍然大悟:"减少了元数据开销。"

"不仅如此,"巨树说,"extent 还能描述空洞。如果文件中间有一段没有写过,extent 可以跳过这段——不分配磁盘块。sparse file 就是这么实现的。"

林小源蹲下来,在地上画了两个对比图:左边是一串间接块指针,层层嵌套;右边是三个 extent,每个 extent 用起始块号和长度就能描述一大片连续区域。

"连续比分散高效,"他说。

"当然,"巨树说,"磁盘喜欢顺序读写。extent 减少了随机访问,提高了性能。"

林小源在巨树的根部发现了一个发光的池子。

池子里的液体是透明的,但表面有一层薄薄的油膜,油膜上不断有微小的气泡升起又破裂。

"这是延迟分配池,"巨树说,"ext4 的另一个妙招。"

"延迟分配?"

"写入的时候,数据先进这个池子,"巨树说,"不立即分配磁盘块。等到回写的时候,内核已经知道了所有数据的大小和位置——可以一次性分配一大片连续的块。"

林小源蹲下来,观察池子里的气泡。每个气泡都是一个待写入的数据块,它们在池子里漂浮,等待被分配到磁盘上的位置。

"如果不延迟呢?"

"写一个字节就分配一个块,"巨树说,"碎片化严重。大文件被切成无数小块,散布在磁盘各处。读取的时候,磁头要到处跳——性能暴跌。"

林小源站起身,拍了拍手上的泥土。他看着巨树——ext4 比他想象的要复杂得多。extent、延迟分配、日志、多块分配——每一个特性都是多年打磨的结果。

"你很老了?"他问。

"ext3 的儿子,"巨树说,"ext2 的孙子。三代人的积累,都在我身上。"

他蹲下来数了数巨树的年轮——哪里是什么年轮,分明是一个个 block group,各自管着自己的一亩三分地。


c
/*
 * ext4 的磁盘布局:
 *
 *   Boot Block | Block Group 0 | Block Group 1 | ...
 *
 * 每个 Block Group 包含:
 *   - Superblock(备份)
 *   - Group Descriptors
 *   - Block Bitmap
 *   - Inode Bitmap
 *   - Inode Table
 *   - Data Blocks
 *
 * ext4 的特性:
 *   - 最大文件: 16TB
 *   - 最大文件系统: 1EB
 *   - 日志(JBD2)
 *   - extent(替代间接块)
 *   - 延迟分配
 *   - 多块分配
 */

printf("=== ext4 — 最常用的文件系统 ===\n\n");

printf("ext4 磁盘布局:\n");
printf("  ┌─────────────────────────────────────┐\n");
printf("  │ Boot Block (1KB)                    │\n");
printf("  ├─────────────────────────────────────┤\n");
printf("  │ Block Group 0                       │\n");
printf("  │  ├── Superblock                     │\n");
printf("  │  ├── Group Descriptors              │\n");
printf("  │  ├── Block Bitmap                   │\n");
printf("  │  ├── Inode Bitmap                   │\n");
printf("  │  ├── Inode Table                    │\n");
printf("  │  └── Data Blocks                    │\n");
printf("  ├─────────────────────────────────────┤\n");
printf("  │ Block Group 1                       │\n");
printf("  │  └── ...                            │\n");
printf("  └─────────────────────────────────────┘\n\n");

printf("--- ext4 的特性 ---\n");
printf("1. extent\n");
printf("   替代传统的间接块\n");
printf("   一个 extent 描述连续的数据块\n");
printf("   减少元数据开销\n\n");
printf("2. 延迟分配\n");
printf("   写入时不立即分配磁盘块\n");
printf("   等到写回时再分配\n");
printf("   减少碎片\n\n");
printf("3. 日志(JBD2)\n");
printf("   记录元数据操作\n");
printf("   崩溃后快速恢复\n\n");
printf("4. 多块分配\n");
printf("   一次分配多个连续块\n");
printf("   提高大文件性能\n\n");

printf("--- inode 结构 ---\n");
printf("传统 ext2/3 inode:\n");
printf("  12 个直接块指针\n");
printf("  1 个间接块指针\n");
printf("  1 个二级间接块指针\n");
printf("  1 个三级间接块指针\n\n");
printf("ext4 inode:\n");
printf("  使用 extent tree\n");
printf("  每个 extent 描述连续块\n");
printf("  更高效\n\n");

printf("--- ext4 vs ext3 ---\n");
printf("ext3: 最大 2TB 文件, 16TB 文件系统\n");
printf("ext4: 最大 16TB 文件, 1EB 文件系统\n");
printf("ext4: extent, 延迟分配, 日志校验\n");

道藏笔记

内核启示

ext4 是 Linux 世界用得最多的文件系统,七成以上的 Linux 机器都在用它。

它的磁盘被分成一个个 Block Group,每个 Group 里都有 superblock 的备份、Group Descriptor、Block Bitmap、Inode Bitmap、Inode Table 和数据区。坏了一个 Group,其他的不受影响——这叫故障隔离。

ext4 相比 ext3 最大的进步是 extent。传统的间接块指针要层层跳转才能找到数据块,extent 直接说"从第 100 块开始,连续 500 块都是我的",一个结构就描述了一大片连续区域。再加上延迟分配——写入时不急着分配磁盘块,等到回写时再统一分配,减少碎片。这两个特性加在一起,大文件的性能比 ext3 好得多。

日志(JBD2)保证了崩溃后能快速恢复,多块分配让大文件的写入更高效。ext3 的儿子,ext2 的孙子,三代人的积累都在它身上。


破关试炼

ext4 之试

ext4 写入时不急着分配磁盘块、等回写再统一安排的特性叫什么?

答对后才能继续滑动和进入下一章。

以修仙之名,悟内核之道