☰
Ext文件系统(2)软件系统
2026/9/26 3:45:09 网站建设 项目流程

一、宏观图景:分区 → 块组 → 六件套

一块磁盘可以划分多个分区,每个分区可以有自己独立的一套文件系统(ext2/3/4、NTFS……),即文件系统以分区为单位。

分区内部再按Block Group(块组)切分,每个块组包含六件套:

组件作用
Super Block文件系统全局信息(分区有多大、块组怎么分)
GDT(Group Descriptor Table)块组描述符表,描述每个块组
Block Bitmap块位图:哪个数据块被占用
inode Bitmapinode 位图:哪个 inode 被占用
inode Tableinode 表:存所有 inode(属性)
Data Blocks数据块:存文件内容

二、块(Block):为什么是 4KB

  • 磁盘物理扇区是512B,但操作系统读写的基本单位是4KB 的块(Block)
  • 为什么不用 512B?
    • 软硬件解耦:磁盘技术更新(512B → 4K 扇区),OS 不必跟着改;偶合度低
    • 效率考量:小粒度读写导致 IO 次数暴增
  • 💡 内存管理的页也是 4KB ——磁盘块天然就是为载入内存准备的

三、inode:文件的属性卡片

  • inode = struct inode 结构体对象,大小固定128 字节,直接以二进制写盘
    • 字段类型固定:类型 int、权限 char/short、大小 long long……
  • 为什么文件名不存 inode?
    • ✖ 文件名是变长字符串,会破坏 128B 固定大小的设计
    • ✔ 文件名保存在所属目录的数据块中(见第五节)
  • inode Table本身也是数据块:
    • 一块 4KB = 4096 / 128 =32 个 inode
    • 访问一个文件属性时,文件系统把整个 4KB 块搬进内存——一次读 32 个 inode
    • 💡 局部性原理:跟 vector 扩容一个思路,多拿一点备着
  • inode 编号:每个文件有唯一编号,ls -li查看
    • 根目录 inode 编号 =2(编号 0、1 保留)

四、位图与超级块:管理数据的"管理数据"

文件系统不仅要存文件,还要管理"哪些块/哪些 inode 被用了"——于是有了管理数据的管理数据。

4.1 Block Bitmap(块位图)

  • 1 个比特对应 1 个数据块:比特为 1 → 占用;为 0 → 空闲
  • 10 万个 DataBlock → 位图 10 万比特 ≈3~4 个数据块
  • 申请数据块 = 对应比特置 1;释放 =清零

4.2 inode Bitmap(inode 位图)

  • 同理,1 个比特对应 1 个 inode

💡删除/恢复文件的本质:

  • 删除 = 两个位图中对应比特清零(属性和内容根本没动)
  • 恢复 = 把比特重新置 1(只要数据块没被别人覆盖)

所以"删除"是 O(1) 的逻辑删除,这也是误删文件有可能被救回来的原理。

4.3 GDT(块组描述符)

  • 描述每一个块组的信息:该组的位图在哪、inode 表在哪、空闲块多少……

4.4 Super Block(超级块)

  • 描述整个分区/文件系统的全局信息:块大小、块组数量、inode 总数……
  • ✖ 它是全局唯一的,一旦损坏整个分区报废——所以多个块组里都有它的备份

4.5 格式化的本质

  • ✔ 格式化 ≠ 清空内容,而是向分区写入文件系统的管理信息(SuperBlock / GDT / 位图 / 分组结构)

4.6 inode 定位公式

  • 已知 inode 编号 N:块组号 = N / 每组inode数,组内偏移 = N % 每组inode数
  • 开机时 OS 把管理信息(SuperBlock、位图等)加载进内存——先描述、再组织

五、目录的本质:也是文件

震惊点:目录和普通文件的存储方式完全一样(inode + 数据块),只是 inode 的 type 字段不同。

  • 目录的数据块里存的是一张映射表:该目录下所有「文件名 ↔ inode 编号」
  • 磁盘上没有"目录"这个概念,只有 inode + block,靠 type 区分
  • 同目录下文件名唯一:文件名唯一 + inode 唯一,互为键值,所以磁盘层面无重复

六、路径解析:进程文件的产生和缓存的底层全流程

大体思路:进程(task_struct)中有个存了指向file_struct指针的结构体,结构体里面的指针都是指向跟当前进程相关的文件,通过表找到对应的file_struct,file_struct中还存在了dentry结构体,通过dentry结构体可以找到对应的其他dentry结构体,最后组成缓存多叉树

6.1 谁提供路径?

  • 文件名:用户提供的
  • 路径:进程提供的——进程 PCB 里有 cwd(当前工作目录),由 bash 继承而来,最终源自系统环境 PWD
  • 用户文件名 + cwd → 拼出绝对路径

6.2 解析流程

  1. 打开当前目录 → 读它的数据块(映射表)
  2. 找到文件名对应的 inode 编号
  3. 编号 → 除模定位块组 → 查 inode Bitmap → 找到 inode Table 中的位置
  4. 把 inode 属性加载进内存 → 打印

💡路径解析必须从根目录开始(递归):

  • 访问文件要先打开所在目录,找目录又要找上级目录……一路递归到根
  • 根目录在开机时就被 OS 打开了,这是一切的起点

6.3 效率问题 → dentry 缓存多叉树

  • 每次都从根开始解析 = 大量磁盘 IO,太慢

  • ✔ Linux 在内存中动态构建目录树缓存:每一个节点都是一个dentry结构体,历史访问过的路径形成一棵多叉树,他们通过父子指针连在一起。

  • struct dentry关键字段:引用计数、flags、inode 指针、d_parent、subdirs、LRU 链表、lookup 哈希链

  • 💡一个节点多重挂靠:既在多叉树上(路径查找)、又在 LRU 链表上(淘汰)、又在哈希表上(快速查找)

  • 实测:find /第一次慢(树不完善,要磁盘 IO),第二次快(内存命中)

七、挂载(mount):分区与目录的绑定

7.1 为什么要挂载

  • inode 编号不能跨分区(不同分区各有一套编号)
  • 那"我怎么知道文件在哪个分区"?——分区必须与一个目录关联起来才能使用,这就是挂载
  • cd 进入挂载点目录 = 进入那个分区

7.2 实操:dd 制作伪磁盘 + 挂载(知道原理即可)

# 1. 造一个 5MB 的大文件当"磁盘"ddif=/dev/zeroof=disk.imgbs=1MBcount=5# 2. 格式化成 ext4(写入管理信息)mkfs.ext4 disk.img# 输出关键信息:block size = 1024,1280 inodes,5120 blocks# 3. 挂载到一个空目录mkdirdirmount-text4 disk.imgdir# 4. 查看挂载情况df-h# 5. 卸载umountdir

7.3 路径前缀最近匹配原则

  • 文件路径前缀含哪个挂载点,文件就在哪个分区
  • 嵌套挂载时用最近(最深)前缀匹配

八、fopen 时 OS 做了什么(全流程串联)

路径解析(查 dentry 树) → 找到 inode → 内核创建 struct file(含缓冲区、操作表填充) → 创建 struct inode(inode 属性加载进内存) → fd 表分配 → 返回 fd
  • 用户拿到 fd,后续 read/write 全靠它
  • 💡 这就是"一切文件操作,先打开、后使用"的底层含义

九、软链接与硬链接

9.1 硬链接(hard link)

  • ln 目标 新名字
  • 同一个 inode,多个文件名——目录映射表里多条记录指向同一 inode 编号
  • inode 里的链接计数记录有几个名字指向它
  • 删除一个名字 = 计数减 1;计数归 0 才真正释放(位图清零)
  • ✖ 不能跨分区(inode 编号不跨分区)、不能对目录建硬链接

9.2 软链接(soft link / 符号链接)

  • ln -s 目标 新名字
  • 独立的 inode(独立文件),数据块里存的是目标的路径字符串
  • 访问软链接 = 读出路径 → 重新做路径解析
  • 软链接的用处,为什么要软链接:可以跨分区、可以指向目录;可以把一个可执行程序快捷方式到当前目录下,方便我们执行。
  • 软链接目标被删后成为悬空链接

9.3 对比

硬链接软链接
inode与目标同一个独立inode
本质目录项中的映射记录独立文件,存目标路径
跨分区✖✔
链接目录✖✔
目标删除后依然可用(计数未归 0)悬空失效

十、知识点小总结

问题答案
文件系统以什么为单位?分区;分区内再切块组
块多大?4KB(内存页同款,软硬件解耦)
inode 多大?存什么?128B,存属性;不存文件名
一块 inode Table 多少 inode?4096/128 =32 个
文件名存哪?所属目录的数据块(文件名↔inode 映射表)
删除文件的本质?位图清零,数据不动
格式化的本质?写入管理信息(SB/GDT/位图/分组)
inode 怎么定位?编号除模:组号 = N/每组数,偏移 = N%每组数
路径解析从哪开始?根目录(开机已被 OS 打开),dentry 缓存加速
分区怎么用?挂载到目录;前缀最近匹配定分区
硬链接/软链接?硬:同 inode 计数;软:独立 inode 存路径

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询