Linux ext 系列文件系统
Linux 操作系统中的文件系统丐版简图
ext系列文件系统的历史发展
Linux ext4 的硬盘布局
ext4文件系统 使用 i 节点(index node)--inode 来分拆硬盘数据块给到文件。
(了解i节点:juejin.cn/post/758521…
图中可以看到 硬盘中的文件file, ext4文件系统给它分配了 数据块 0,3,n-2,n-1 存储file
linux ext4 的硬盘布局 — 简化版
包括以下几部分:
1.超级块
2.i-bitmap 索引节点位图
3.inode表
4.d-bitmap 数据块位图
5.数据区域
linux ext4 的硬盘布局 — 块组
Liunx ext4为了管理大文件,在上面的基础上,搞了 “块组” 数据结构
struct ext4_group_desc {
__le32 bg_block_bitmap_lo; /* 数据块 位图块号:本组内数据块使用/空闲 bitmap 位置 */
__le32 bg_inode_bitmap_lo; /* inode 位图块号:本组内 inode 使用/空闲 bitmap 位置 */
__le32 bg_inode_table_lo; /* inode 表:本组内所有 inode 结构体的起始块 */
__le16 bg_free_blocks_count_lo; /* 空闲数据块计数: 本组剩余可用数据块总数 */
__le16 bg_free_inodes_count_lo; /* 空闲 inode 计数: 本组剩余可用 inode 总数 */
__le16 bg_used_dirs_count_lo; /* 目录计数:本组已分配的目录 inode 数量,用于均衡分布新目录 */ __le16 bg_flags; /* 标志位:如 INODE_UNINIT,指示该组是否需要初始化等 */
__le32 bg_exclude_bitmap_lo; /* 快照排除位图块号:快照功能中标记跳过复制的块(通常不用) */
};
为了持久化存储“块组”,linux又搞了一个 块组描述符表
超级块(super block) + 块组描述符表(block group table) + 块组(ext4_group_desc)
再一次从宏观上看一下 linux ext4 的硬盘布局
df -h -T 查看linux操作系统中覆盖的文件系统
dumpe2fs /dev/vda1 查看具体文件系统的详细信息
从图中,可以看出操作系统中,有很多文件系统
linux ext4 的硬盘数据结构 — 整理
下图展示了,ext4文件系统对硬盘抽象,定义的一些,数据结构
struct
ext4_inode索引节点struct
ext4_dir_entry目录项struct
ext_group_desc块描述struct
ext4_super_block超级块还有很多很多,可以去官网去查有哪些数据结构,或者AI
Linux ext4 文件和目录如何组织(inode)
由于ext4基于 i 节点(index node)--inode 的缘故,每个文件都会有一个inode,用于保存文件的元数据(metadata)
ext4_inode 数据结构
| 字段 | 含义(中文) |
| i_mode | 文件模式(文件类型 + 权限位,如 0644、0755 等) |
| i_uid | 文件所属用户 ID 的低 16 位 |
| i_size_lo | 文件大小(字节数)的低 32 位 |
| i_atime | 最后访问时间(Access Time) |
| i_ctime | inode 自身状态最后一次改变的时间(Change Time) |
| i_mtime | 文件内容最后修改时间(Modification Time) |
| i_dtime | 文件被删除的时间(仅当文件被删除时有效) |
| i_gid | 文件所属组 ID 的低 16 位 |
| i_links_count | 硬链接计数(有多少个目录项指向该 inode) |
i_blocks_lo | 文件占用的物理块数 - 占用多少个数据块(以 512 字节为单位)的低 32 位 |
| i_flags | 文件标志位(如追加、不可变、压缩等属性) |
| i_block[EXT4_N_BLOCKS] | 数据块指针数组,直接/间接指向文件实际数据块 —— 占用数据块在磁盘中的位置 |
| i_generation | 文件版本号(用于 NFS 等网络文件系统) |
| i_file_acl_lo | 文件 ACL(访问控制列表)的低 32 位 |
| i_size_high | 文件大小的高 32 位,与 i_size_lo 一起组成 64 位文件大小 |
i_block[EXT4_N_BLOCKS]
ext4_dir_entry_2 数据结构
inode 长度:__le32(4 字节,小端)
- 含义:该目录项对应的 inode 编号。0 表示“已删除的空槽位”,非 0 才能解析出真正的文件/子目录。
rec_len 长度:__le16(2 字节,小端)
- 含义:整个 ext4_dir_entry_2 结构**在本目录块中所占的总长度**(字节数)。
因为文件名长度可变,目录项长度也可变;下一个目录项的位置 = 当前地址 + rec_len。
删除文件时不会立即紧凑,只是把 inode 置 0,并把被删项的 rec_len 扩大,形成“空洞”供后续复用。
name_len 长度:u8(1 字节)
- 含义:文件名的**实际字符数**(不含结尾 \0)。最大 255(EXT4_NAME_LEN)。
file_type 长度:u8(1 字节)
- 含义:避免额外读 inode 就能快速知道类型,取值:
0x1 普通文件
0x2 目录
0x3 字符设备
0x4 块设备
0x5 FIFO
0x6 套接字
0x7 符号链接
早期 ext2 没有这个字段,所以旧格式叫 ext4_dir_entry(没有 _2);后来为了提速加了这个字节,就成了 ext4_dir_entry_2。
name[EXT4_NAME_LEN]
- 内容:文件名本身,**不补 \0**,直接紧挨着前面四个字段。
由于整个结构长度必须 4 字节对齐,所以末尾可能再补 1~3 字节空 padding,这些 padding 会计入 rec_len,但不计入 name_len。
一句话总结
------------------------------------------------
ext4_dir_entry_2 就是**目录块里的一条记录**:
“inode 号 + 本记录长度 + 文件名长度 + 文件类型 + 文件名本身”,
内核靠它在目录里“扫大街”——找文件、删文件、创建文件都靠解析这一串。
_le32 inode
目录是特殊的文件,也有自己对应的 inode
Linux ext4文件系统中 文件创建、读写流程
下面几张图简单的概括 ext4文件系统是怎么创建文件,读文件, 写文件
创建一个目录 /fs (简单看看就行)
创建一个文件 /fs/file_1 (简单看看就行)
读取文件 /fs/file_1 的所有 数据块 的数据(简单看看就行)