浅学文件系统2(ext4文件系统)

37 阅读5分钟

Linux ext 系列文件系统

Linux 操作系统中的文件系统丐版简图 image.png ext系列文件系统的历史发展 image.png

Linux ext4 的硬盘布局

ext4文件系统 使用 i 节点(index node)--inode 来分拆硬盘数据块给到文件。 (了解i节点:juejin.cn/post/758521… image.png 图中可以看到 硬盘中的文件file, ext4文件系统给它分配了 数据块 0,3,n-2,n-1 存储file

linux ext4 的硬盘布局 — 简化版

包括以下几部分:

1.超级块

2.i-bitmap 索引节点位图

3.inode表

4.d-bitmap 数据块位图

5.数据区域

image.png

linux ext4 的硬盘布局 — 块组

Liunx ext4为了管理大文件,在上面的基础上,搞了 “块组” 数据结构 image.png

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)

image.png 再一次从宏观上看一下 linux ext4 的硬盘布局 image.png

df -h -T 查看linux操作系统中覆盖的文件系统 
dumpe2fs /dev/vda1 查看具体文件系统的详细信息

image.png 从图中,可以看出操作系统中,有很多文件系统

linux ext4 的硬盘数据结构 — 整理

下图展示了,ext4文件系统对硬盘抽象,定义的一些,数据结构 image.png

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 数据结构

image.png

字段含义(中文)
i_mode文件模式(文件类型 + 权限位,如 0644、0755 等)
i_uid文件所属用户 ID 的低 16 位
i_size_lo文件大小(字节数)的低 32 位
i_atime最后访问时间(Access Time)
i_ctimeinode 自身状态最后一次改变的时间(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]

image.png

ext4_dir_entry_2 数据结构

image.png

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 image.png

Linux ext4文件系统中 文件创建、读写流程

下面几张图简单的概括 ext4文件系统是怎么创建文件读文件写文件

创建一个目录 /fs (简单看看就行) image.png 创建一个文件 /fs/file_1 (简单看看就行) image.png 读取文件 /fs/file_1 的所有 数据块 的数据(简单看看就行) image.png