【Linux】ext2文件系统深度剖析——块组、位图、inode与数据块映射

目录

[1. 引言](#1. 引言)

[2. ext2的整体布局](#2. ext2的整体布局)

[3. 超级块(Super Block)](#3. 超级块(Super Block))

[4. 块组描述符表(GDT)](#4. 块组描述符表(GDT))

[5. 位图(Bitmap)](#5. 位图(Bitmap))

[6. inode表(Inode Table)](#6. inode表(Inode Table))

[7. 数据块(Data Blocks)](#7. 数据块(Data Blocks))

[8. inode与数据块的映射------直接、间接块索引](#8. inode与数据块的映射——直接、间接块索引)

[9. 创建一个新文件的过程(以touch abc为例)](#9. 创建一个新文件的过程(以touch abc为例))

[10. 删除文件的过程](#10. 删除文件的过程)

[11. 小结](#11. 小结)


1. 引言

ext2是Linux经典的日志文件系统之一,ext3/ext4在其基础上增加了日志功能和大文件支持,但核心磁盘布局保持一致。本文将详细拆解ext2文件系统的块组结构,分析超级块、块组描述符、位图、inode表和数据块的作用,并解释inode如何通过直接、间接块索引找到文件数据。

2. ext2的整体布局

一个ext2分区被划分为若干个块组(Block Group),每个块组的大小相等。块组的目的是将磁盘分组管理,避免超级块等元数据过于集中,提高可靠性。

每个块组包含以下部分(按顺序排列):

组件 作用
超级块(Super Block) 描述整个文件系统的全局信息
块组描述符表(GDT) 每个块组一个描述符,记录该组的位图、inode表位置等
块位图(Block Bitmap) 标记该组数据块是否空闲
inode位图(Inode Bitmap) 标记该组inode是否空闲
inode表(Inode Table) 连续存放该组所有inode结构
数据块(Data Blocks) 实际存储文件内容或目录项

注意:超级块和GDT在每个块组的开头都有备份(第一个块组必须有,后面的可选),以防损坏。

3. 超级块(Super Block)

超级块存储文件系统的全局元数据,如:

  • inode总数、空闲inode数

  • 数据块总数、空闲块数

  • 块大小、每块组块数、每块组inode数

  • 文件系统状态、最后挂载时间等

内核中struct ext2_super_block定义了这些字段(详见文档)。超级块损坏会导致整个文件系统无法挂载。

4. 块组描述符表(GDT)

每个块组在GDT中有一个struct ext2_group_desc条目,包含:

  • bg_block_bitmap:块位图所在的块号

  • bg_inode_bitmap:inode位图所在的块号

  • bg_inode_table:inode表起始块号

  • bg_free_blocks_count:该组空闲块数

  • bg_free_inodes_count:该组空闲inode数

  • bg_used_dirs_count:该组目录数

通过GDT,操作系统可以快速定位每个块组的管理信息。

5. 位图(Bitmap)

  • 块位图:每个bit对应一个数据块,1表示已分配,0表示空闲。

  • inode位图:每个bit对应一个inode,1表示已使用,0表示空闲。

创建新文件时,文件系统会在位图中查找空闲inode和空闲数据块,分配后置位。

6. inode表(Inode Table)

  • 连续存储一组inode结构(每个inode固定大小,如128字节)。

  • inode号从1开始,全局唯一(整个分区内)。inode号可以计算出它属于哪个块组以及在该组inode表中的偏移。

inode与块组的对应关系:

设每个块组有inodes_per_group个inode,则inode号N属于块组(N-1) / inodes_per_group,组内索引为(N-1) % inodes_per_group

7. 数据块(Data Blocks)

  • 存储文件的实际内容(普通文件)或目录项列表(目录文件)。

  • 文件系统使用块号访问数据,块号是相对于分区起始的,不能跨分区。

8. inode与数据块的映射------直接、间接块索引

每个inode中包含15个i_block指针(EXT2_N_BLOCKS = 15),它们组成一个多级索引结构:

text

复制代码
i_block[0]  ───► 直接块(12个)
i_block[1] 
...
i_block[11]
i_block[12] ───► 一级间接块(指向一个数据块,该块内存储多个块号)
i_block[13] ───► 二级间接块
i_block[14] ───► 三级间接块

计算最大文件大小(以4KB块、4字节块号为例):

  • 直接块:12 * 4KB = 48KB

  • 一级间接:一个块可存放 4KB/4 = 1024 个块号 → 1024 * 4KB = 4MB

  • 二级间接:1024 * 1024 * 4KB = 4GB

  • 三级间接:1024 * 1024 * 1024 * 4KB = 4TB

因此ext2支持的最大文件大小为4TB(受限于块号和块大小)。

9. 创建一个新文件的过程(以touch abc为例)

  1. 分配inode:扫描inode位图,找到空闲inode(如inode 263466),将其标记为使用,并将文件属性(大小、权限、时间等)写入inode表。

  2. 分配数据块 :根据文件内容大小,从块位图中找空闲块(如300、500、800),将这些块号填入inode的i_block数组(或间接块)。

  3. 记录分配:将块号列表写入inode的块指针区域。

  4. 添加目录项 :在当前目录的数据块中增加一条记录,包含文件名abc和inode号263466。

10. 删除文件的过程

  1. 在目录中找到文件名对应的inode号。

  2. 将该inode的硬链接计数减1(i_links_count--)。

  3. 若硬链接计数变为0,则释放inode(清空inode位图),并释放所有数据块(清空块位图)。

  4. 从目录中删除目录项。

这就是为什么rm删除文件后,数据可能还能恢复(只要块未被覆盖)。

11. 小结

ext2文件系统通过块组、位图、inode表和多级索引实现了对磁盘空间的高效管理。理解这些结构是掌握文件恢复、磁盘修复、性能调优的基础。下一篇我们将讨论目录的实现、路径解析、挂载以及软硬链接。