1. Ext4 文件系统概述

Ext4(Fourth Extended Filesystem)是 Linux 内核中最广泛使用的本地文件系统之一,自 2008 年随 Linux 2.6.28 内核正式合入以来,已成为企业级服务器、嵌入式设备和桌面系统的默认选择。Ext4 并非全新设计,而是从 Ext3 演进而来,在保持向后兼容的同时,大幅提升了扩展性、性能和可靠性。

1.1 Ext4 发展历史

时间 里程碑 关键变化
1992 Ext2 发布 首个 Linux 原生文件系统,无日志功能
2001 Ext3 发布 在 Ext2 基础上增加日志(JBD),支持有序/回写/预提交模式
2006 Ext4 开发启动 由 Ext3 维护者 Theodore Ts'o 领导,引入扩展(Extent)和 48 位块号
2008 Linux 2.6.28 Ext4 标记为稳定,正式合入主线内核
2010+ 持续优化 在线 defrag、快速扩展、延迟分配、checksum 等特性逐步加入
关键认知:Ext4 的磁盘格式与 Ext3 兼容,但 Ext4 的 on-disk 结构引入了大量新字段。挂载时若使用 ext3 驱动读取 Ext4 分区,将丢失扩展、纳秒时间戳等高级特性。

1.2 Ext4 核心特性

  • 扩展(Extent)树:取代 Ext3 的间接块映射,使用 B+ 树管理连续物理块,减少元数据开销,提升大文件读写性能。
  • 48 位块号:支持最大 1 EiB(2^48 × 4 KiB)的文件系统和 16 TiB 的单个文件。
  • 延迟分配(Delayed Allocation):将块分配推迟到数据回写时,提高连续块分配概率,减少碎片。
  • 纳秒时间戳:文件时间戳精度从秒级提升到纳秒级,满足数据库等高性能应用需求。
  • 预分配(Fallocate):通过 fallocate() 系统调用预先分配物理空间,避免运行时 ENOSPC。
  • 在线 defrag:支持文件系统挂载时进行碎片整理(e4defrag)。
  • 快速扩展(Flexible Block Groups):将多个块组聚合成 flex_bg,减少元数据寻道时间。
  • 校验和(Metadata Checksum):对日志、目录、位图等关键元数据提供 CRC32 校验,增强数据完整性。

1.3 Ext4 与 Ext3 关键区别

对比维度 Ext3 Ext4
块寻址方式 间接块映射(三级间接) 扩展树(Extent Tree)
最大文件系统 16 TiB(32 位块号) 1 EiB(48 位块号)
最大文件大小 2 TiB 16 TiB
子目录数量 32,000(传统限制) 64,000(Htree 索引)
时间戳精度 秒 纳秒
块分配策略 即时分配 延迟分配 + 多块分配
日志机制 JBD(Journaling Block Device) JBD2(增强版,支持 64 位日志块号)
元数据校验 无 CRC32 校验和
在线 defrag 不支持 支持(e4defrag)
性能对比要点:Ext4 的扩展树和延迟分配在顺序读写大文件时比 Ext3 快 2-4 倍;但在小文件随机写入场景下,延迟分配可能增加数据丢失风险(断电时未分配块丢失),需配合日志模式使用。

1.4 磁盘布局简介

Ext4 将磁盘划分为多个 块组(Block Group),每个块组包含连续的块。块组是 Ext4 管理空间的基本单元,其内部结构如下:

Ext4 磁盘布局 — 块组结构 超级块 (Superblock) — 块组 0 起始位置,备份在块组 1、3、5、7… 块组描述符表 (Group Descriptor Table) — 每个块组 64 字节描述符 块组 0 块位图 (Block Bitmap) inode 位图 (Inode Bitmap) inode 表 (Inode Table) 数据块 (Data Blocks) 文件/目录内容存储区 块组 1 块位图 inode 位图 inode 表 数据块 块组 N 块位图 inode 位图 inode 表 数据块 … … 磁盘布局关键说明: • 超级块:文件系统全局信息(块大小、inode 数、挂载时间等),块组 0 起始位置,每隔 128 个块组备份一次。 • 块组描述符表:每个块组一个 64 字节描述符,记录块位图、inode 位图、inode 表的起始块号。 • 块位图 / inode 位图:每个 bit 表示一个块或 inode 的分配状态(1=已用,0=空闲)。 • inode 表:存储文件元数据(权限、时间戳、扩展树根节点指针等),每个 inode 256 字节。

1.5 块组内部结构详解

每个块组的大小由文件系统块大小决定(默认 4 KiB)。块组内的元数据布局遵循固定顺序:

  1. 超级块(Superblock):仅块组 0 和备份块组包含,存储文件系统全局参数。
  2. 块组描述符表(Group Descriptor Table):紧随超级块之后,每个块组对应一个描述符。
  3. 块位图(Block Bitmap):占用 1 个块,标记本块组内所有数据块的分配状态。
  4. inode 位图(Inode Bitmap):占用 1 个块,标记本块组内所有 inode 的分配状态。
  5. inode 表(Inode Table):连续存储多个 inode 结构,默认每 4 KiB 块可存放 16 个 inode(256 字节/个)。
  6. 数据块(Data Blocks):剩余空间用于存储文件数据和目录条目。
性能陷阱:当文件系统碎片化严重时,一个文件的数据块可能分散在多个块组中,导致读取时需要跨块组寻道。Ext4 的延迟分配和 flex_bg 特性正是为了缓解此问题。在调优时,可通过 e2fsck -fn /dev/sdX 检查碎片率,若碎片率 > 10%,建议执行 e4defrag 整理。

1.6 Ext4 日志与 JBD2 的定位

Ext4 的日志功能由 JBD2(Journaling Block Device 2) 层实现。JBD2 是 Ext3 中 JBD 的升级版,主要改进包括:

  • 支持 64 位日志块号,适配 Ext4 的大容量需求。
  • 支持日志校验和(Journal Checksum),增强崩溃恢复可靠性。
  • 支持异步日志提交(Async Commit),减少日志提交延迟。

JBD2 在 Ext4 中的位置如下图所示:

Ext4 日志架构 — JBD2 层位置 用户态应用 (open/read/write/fsync) VFS (Virtual File System) 层 Ext4 文件系统层 inode 操作 / 目录操作 / 扩展树管理 JBD2 日志层 事务管理 / 日志提交 / 崩溃恢复 块设备层 (Block Layer / I/O Scheduler) 磁盘 (Disk) — 数据区 + 日志区 (Journal Area) Ext4 通过 JBD2 接口将元数据变更记录到日志区,崩溃后通过日志回放恢复一致性