ext2(Second Extended File System)是Linux早期广泛使用的文件系统,虽然现在逐渐被ext3/ext4取代,但理解其物理结构对掌握Linux文件系统原理非常重要。
ext2文件系统在物理磁盘上的布局如下:
+-------------------+------------------+------------------+-----+------------------+
| Boot Block | Super Block | Block Group 0 | ... | Block Group N |
+-------------------+------------------+------------------+-----+------------------+
超级块存储文件系统的全局信息,主要包含:
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)
// ... 其他字段省略
};
超级块在每个块组都有备份,防止损坏导致整个文件系统不可用。
每个块组包含以下部分:
+----------------+----------------+----------------+----------------+----------------+
| Super Block | Group Descriptor | Block Bitmap | Inode Bitmap | Inode Table | Data Blocks |
+----------------+----------------+----------------+----------------+----------------+
描述块组的信息:
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]; // 保留
};
块大小×8
个块存储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:三级间接指针
实际存储文件内容的块,大小可以是1024、2048或4096字节。
目录在ext2中是一种特殊文件,其内容是由以下结构组成的列表:
struct ext2_dir_entry_2 {
__le32 inode; // inode号
__le16 rec_len; // 目录项长度
__le8 name_len; // 文件名长度
__le8 file_type; // 文件类型
char name[]; // 文件名(变长)
};
查找 /home/user/file.txt
的过程:
1. 从根inode(通常为2号)开始
2. 在根目录数据块中查找"home"对应的inode
3. 在home目录数据块中查找"user"对应的inode
4. 在user目录数据块中查找"file.txt"对应的inode
5. 通过file.txt的inode访问文件数据块
ext2文件系统的这种结构设计在机械硬盘时代非常高效,但缺乏日志功能是其被后续版本替代的主要原因。