插件窝 干货文章 Linux下ext2文件系统的物理结构详解

Linux下ext2文件系统的物理结构详解

inode 文件 Block 大小 944    来源:    2025-04-09

Linux ext2文件系统物理结构详解

ext2(Second Extended File System)是Linux早期广泛使用的文件系统,虽然现在逐渐被ext3/ext4取代,但理解其物理结构对掌握Linux文件系统原理非常重要。

1. ext2文件系统整体布局

ext2文件系统在物理磁盘上的布局如下:

+-------------------+------------------+------------------+-----+------------------+
| Boot Block | Super Block | Block Group 0 | ... | Block Group N |
+-------------------+------------------+------------------+-----+------------------+
  • Boot Block:引导块,存放引导程序(前1024字节)
  • Super Block:超级块,记录整个文件系统的全局信息
  • Block Group:块组,文件系统被划分为多个块组

2. 超级块(Super Block)

超级块存储文件系统的全局信息,主要包含:

struct ext2_super_block {
    __le32  s_inodes_count;         // 文件系统中inode总数
    __le32  s_blocks_count;         // 文件系统中块总数
    __le32  s_r_blocks_count;       // 保留块数
    __le32  s_free_blocks_count;    // 空闲块数
    __le32  s_free_inodes_count;    // 空闲inode数
    __le32  s_first_data_block;     // 第一个数据块
    __le32  s_log_block_size;       // 块大小(0=1K,1=2K,2=4K)
    __le32  s_log_frag_size;        // 片段大小(已废弃)
    __le32  s_blocks_per_group;     // 每块组块数
    __le32  s_frags_per_group;      // 每块组片段数(已废弃)
    __le32  s_inodes_per_group;     // 每块组inode数
    __le32  s_mtime;                // 挂载时间
    __le32  s_wtime;                // 写入时间
    __le32  s_mnt_count;            // 挂载计数
    __le32  s_max_mnt_count;        // 最大挂载计数
    __le32  s_magic;                // 魔数(0xEF53)
    // ... 其他字段省略
};

超级块在每个块组都有备份,防止损坏导致整个文件系统不可用。

3. 块组(Block Group)结构

每个块组包含以下部分:

+----------------+----------------+----------------+----------------+----------------+
| Super Block | Group Descriptor | Block Bitmap | Inode Bitmap | Inode Table | Data Blocks |
+----------------+----------------+----------------+----------------+----------------+

3.1 块组描述符(Group Descriptor)

描述块组的信息:

struct ext2_group_desc {
    __le32  bg_block_bitmap;        // 块位图块号
    __le32  bg_inode_bitmap;        // inode位图块号
    __le32  bg_inode_table;         // inode表起始块号
    __le16  bg_free_blocks_count;   // 本组空闲块数
    __le16  bg_free_inodes_count;   // 本组空闲inode数
    __le16  bg_used_dirs_count;     // 本组目录数
    __le16  bg_pad;                 // 填充
    __le32  bg_reserved[3];         // 保留
};

3.2 块位图(Block Bitmap)

  • 每个bit代表一个数据块的使用状态(1=已用,0=空闲)
  • 大小为一个块(block),因此一个块组最多管理 块大小×8 个块

3.3 inode位图(Inode Bitmap)

  • 每个bit代表一个inode的使用状态(1=已用,0=空闲)
  • 大小为一个块(block)

3.4 inode表(Inode Table)

存储inode的数组,每个inode结构为:

struct ext2_inode {
    __le16  i_mode;         // 文件类型和权限
    __le16  i_uid;          // 所有者UID低16位
    __le32  i_size;         // 文件大小(字节)
    __le32  i_atime;        // 最后访问时间
    __le32  i_ctime;        // 创建时间
    __le32  i_mtime;        // 最后修改时间
    __le32  i_dtime;        // 删除时间
    __le16  i_gid;          // 组ID低16位
    __le16  i_links_count;  // 硬链接计数
    __le32  i_blocks;       // 占用块数(512字节为单位)
    __le32  i_flags;        // 文件标志
    union {
        struct {
            __le32  l_i_reserved1;
        } linux1;
        // ... 其他OS特定字段省略
    } osd1;
    __le32  i_block[EXT2_N_BLOCKS]; // 指向数据块的指针数组
    // ... 其他字段省略
};

其中 i_block 数组包含15个元素,采用多级索引方式: - 0-11:直接指针(指向数据块) - 12:一级间接指针(指向包含指针的块) - 13:二级间接指针 - 14:三级间接指针

3.5 数据块(Data Blocks)

实际存储文件内容的块,大小可以是1024、2048或4096字节。

4. 目录结构

目录在ext2中是一种特殊文件,其内容是由以下结构组成的列表:

struct ext2_dir_entry_2 {
    __le32  inode;          // inode号
    __le16  rec_len;        // 目录项长度
    __le8   name_len;       // 文件名长度
    __le8   file_type;      // 文件类型
    char    name[];         // 文件名(变长)
};

5. 文件查找示例

查找 /home/user/file.txt 的过程: 1. 从根inode(通常为2号)开始 2. 在根目录数据块中查找"home"对应的inode 3. 在home目录数据块中查找"user"对应的inode 4. 在user目录数据块中查找"file.txt"对应的inode 5. 通过file.txt的inode访问文件数据块

6. 关键参数计算

  • 块组数量 = ceil(总块数 / 每块组块数)
  • 每个块组实际块数 = min(总块数 - 已分配块数, s_blocks_per_group)
  • 最大文件大小取决于索引结构:
    • 直接块:12 × 块大小
    • 一级间接:(块大小/4) × 块大小
    • 二级间接:(块大小/4)^2 × 块大小
    • 三级间接:(块大小/4)^3 × 块大小

ext2文件系统的这种结构设计在机械硬盘时代非常高效,但缺乏日志功能是其被后续版本替代的主要原因。