Appearance
文件系统的全局结构
2026 大纲 四(三)1 文件系统的全局结构(layout),补充说明把它切成两半:文件系统在外存中的结构、在内存中的结构。
前面那些结构,在盘上和内存里各摆在哪
到这里,文件系统的零件已经全了:目录项、inode、数据块、 还有下一节要讲的空闲空间管理结构。但它们在磁盘上是怎么排的?
不能随便排。有一条硬约束:越是必须先读到的,越要放在前面, 而且位置得是约定死的。因为读第一样东西的时候,你还什么都不知道。
顺着这条约束往下推,一个分区的布局就唯一确定了:
引导块必须在最前面——固件只会按固定位置去读它, 它自己不认识任何文件系统(操作系统引导讲过这一层)。 接着是超级块——它记着"块多大、总共几块、inode 区从哪开始、根目录是几号", 不先读它,后面几个区在哪都不知道。再往后是空闲空间管理区和 inode 区, 位置由超级块描述。最后数据块区吃掉剩下的全部空间。
这条链也解释了两件事。超级块坏了整个文件系统就废—— 后面所有区域的位置都靠它描述,所以实际系统会在盘上存多个副本。 inode 区的大小在格式化时定死——它是定长表项的连续数组, 长度必须写进超级块,否则 inode 号就没法由位置隐含推出; 于是会出现"磁盘还有大把空闲块,却创建不了新文件"。
内存那一侧是另一套结构,但逻辑相同:把访问频繁、每次都要读盘的东西缓存起来。 本节后半部分讲它,以及"文件系统能管什么、管不了什么"这条边界—— 它比看起来更容易答错。
一、文件系统的层次结构
| 层次 | 职责 |
|---|---|
| 用户接口 | 提供 open/read/write/close 等系统调用 |
| 文件目录系统 | 管理目录,将文件名转换为 FCB/inode |
| 存取控制模块 | 验证访问权限 |
| 逻辑文件系统 | 将逻辑地址转换为物理地址 |
| 物理文件系统 | 管理磁盘块的分配和回收 |
| 设备驱动程序 | 与磁盘硬件交互 |
二、文件系统在外存中的结构
磁盘 → 分区 → 文件系统这三级,是磁盘那篇"低级格式化 → 分区 → 高级格式化"三步的产物:分区在整块盘上划一次,文件系统在每个分区上各建一次。
┌─────────────┬───────────┬───────────┬──────────┐
│ MBR │ 分区1 │ 分区2 │ 分区3 │
│ (主引导记录) │(文件系统1)│(文件系统2)│(交换区) │
└─────────────┴───────────┴───────────┴──────────┘
┌────────┬────────┬──────────┬───────────┬──────────────┐
│引导块 │ 超级块 │空闲空间管理│ inode 区域 │ 数据块区域 │
│(Boot │(Super │(位图/链表)│(inode │ (Data │
│ Block) │ Block) │ │ Table) │ Blocks) │
└────────┴────────┴──────────┴───────────┴──────────────┘| 区域 | 内容 | 说明 |
|---|---|---|
| 引导块 | 引导程序 | 每个分区的起始位置,用于启动该分区上的 OS |
| 超级块 | 文件系统元信息 | 文件系统类型、块大小、块数量、空闲块数、inode 数等 |
| 空闲空间管理 | 位图或链表 | 记录哪些磁盘块/inode 是空闲的 |
| inode 区域 | inode 表 | 存放所有 inode,按编号连续排列 |
| 数据块区域 | 文件数据 | 存放目录和文件的实际数据 |
整条引导链见操作系统引导。超级块在挂载时读入内存、运行中在内存修改、卸载时写回磁盘。
inode 区大小定死会导致什么:8 GB 分区能建多少文件、什么时候先耗尽(想看清"两种资源谁是瓶颈"是怎么算出来的时展开)
自造数据:某分区容量 8 GB,块大小 4 KB,格式化时按"每 16 KB 空间配一个 inode"的比例划分 inode 区,每个 inode 占 128 B。
(1)inode 个数与 inode 区大小。
占整个分区的
(2)文件数上限 = inode 数 = 524 288 个。 一个文件(含目录)至少要一个 inode。注意判据是"一个 inode 对应一个文件本体"——硬链接不占新 inode(多个目录项共用一个),所以严格说上限是"文件本体数"而非"文件名数"。
(3)若平均文件只有 2 KB,谁先耗尽?
用完全部 inode 时数据才占 1 GB,加上 inode 区的 64 MB,分区里还有约 6.9 GB 是空的,但一个新文件也建不了。把两种资源各自的消耗速度算出来比一比,就能看出谁是瓶颈由文件的平均大小决定——这也是格式化时那个比例要按用途选择的原因:放海量小文件的分区要把比例调密。
三、文件系统在内存中的结构
外存那一半解决"数据在哪",内存这一半解决"怎么不必每次都去外存问":
| 数据结构 | 什么时候建立 | 什么时候销毁 | 每个"什么"一份 |
|---|---|---|---|
| 内存超级块 | 该文件系统被挂载时 | 该文件系统被卸载时(先写回磁盘) | 每个已挂载的文件系统一份 |
| 内存 inode 表 | 某个文件第一次被打开时读入 | 该文件的引用计数降为 0 时(脏则先写回) | 每个正被打开的文件一份 |
| 系统打开文件表 | 每次 open 一个尚未被打开的文件 | 该表项的打开计数降为 0 时 | 每次"打开事件"一份(同一文件被多次 open 时可能多份) |
| 进程打开文件表 | 进程被创建时建表,每次 open 增加一项 | 进程退出时整表销毁,close 时删一项 | 每个进程一张表 |
| 目录项缓存(dentry cache) | 路径解析经过某个目录项时顺手缓存 | 内存紧张时按替换策略淘汰(可随时丢弃) | 每个最近用过的路径分量一项 |
把 open 的五步和这几张表对起来,就知道它们各自为什么存在:
一句话:目录项缓存服务第 ① 步(找 inode 号)、内存 inode 表服务第 ② 步(拿元数据)、两张打开文件表服务第 ④⑤ 步(记住这次打开)。
内存 inode 表与系统打开文件表:分工边界
这两张表最容易混成一张,分工边界只有一条:内存 inode 表描述"文件本体",系统打开文件表描述"一次打开事件"。 由这一条推出全部差别:
| 内存 inode 表 | 系统打开文件表 | |
|---|---|---|
| 一项代表什么 | 一个文件(对应磁盘上一个 inode) | 一次打开(一次 open 调用的结果) |
| 同一文件被 open 两次 | 仍然只有 1 项(引用计数 = 2) | 视实现可有 2 项 |
| 存的字段 | 磁盘 inode 的全部内容 + 引用计数、脏位、锁、设备号 | 打开计数、文件锁、指向内存 inode 表项的指针 |
| 硬链接的两个名字被分别打开 | 共用同一项(它们本来就是同一个 inode) | 各有各的项 |
| 计数归零时 | 写回磁盘 inode 并释放 | 释放表项,并使内存 inode 的引用计数减 1 |
判据:问"这个信息是文件本身的,还是这次打开才有的"——大小、权限、块指针是文件本身的 → 内存 inode 表;读写位置、以什么模式打开的是这次打开才有的 → 打开文件表(本站按通行口径放在进程打开文件表,教材口径的分歧见文件的操作第五节)。
目录项缓存解决什么问题
它解决的是路径解析的重复代价:按目录那篇的结论,解析深度 /home/alice/project/ 下工作时几乎每条路径前 3 级都一样),同一路径又被反复访问(编译一次要打开同一批头文件几十遍)。命中一级就省掉那一级的两次磁盘 I/O(读该目录的 inode + 读它的数据块)。
四、文件系统管什么,管不了什么
有一类题专门考这条边界:给一个功能,问它归文件系统还是归别人。 判据一句话:这件事跟具体是什么硬件有关吗?有关的就不归文件系统。
文件系统是逻辑层,它对下只假设"有一片可按块编号读写的存储", 不假设那是磁片还是闪存。所以:
| 功能 | 归谁 | 为什么 |
|---|---|---|
| 确定盘块大小 | 文件系统 | 盘块是文件系统的逻辑分配单位(把若干连续扇区合成一块),格式化时选定。同一块盘可以格式化成 1 KB / 4 KB / 8 KB 任选,与硬件类型完全无关 |
| 划分扇区 | 硬件 | 机械盘在低级格式化时划、SSD 由控制器决定,文件系统只能接受既成事实 |
| 降低寻道时间 | 磁盘调度(I/O 章) | 它优化的是磁头的机械移动,而 SSD 根本没有寻道这回事 |
| 实现均衡磨损 | SSD 控制器的 FTL | 它是为闪存"擦写次数有限"这个物理特性设计的,机械盘不需要 |
后三项各自只对某一类硬件有意义,所以都不可能是"文件系统能为两种盘都提供的功能"。 只有盘块大小这一项,是文件系统自己定的、且对哪种盘都一样。
考点速记
- 外存布局按"越必须先读到的越靠前"排:引导块 → 超级块 → 空闲空间管理区 → inode 区 → 数据块区。
- MBR 只有一个、引导块每分区一个:MBR 负责"从哪个分区启动",引导块负责"这个分区怎么启动"。三条理由——数量不同、所知范围不同(MBR 那 446 字节不认识任何文件系统)、更新频率不同。
- 超级块存:魔数、块大小、总块数、空闲块数、总/空闲 inode 数、根目录 inode 号、空闲块管理结构的位置。⚠️它一坏整个文件系统就废(后面所有区域的位置都靠它描述),因此常存多个副本。
- inode 区大小在格式化时定死——它是定长表项的连续数组,长度必须写进超级块。由此出现"磁盘还有大量空闲块却创建不了新文件";谁先耗尽由平均文件大小决定。
- 内存五组结构里,内存 inode 表描述文件本体、系统打开文件表描述一次打开事件;三层引用
进程表项 → 系统表项 → 内存 inode → 磁盘 inode每层可多对一。⚠️只有目录项缓存是外存已有信息的纯副本,因而唯一可以随时丢弃。 - 逻辑格式化(高级格式化)建的是:引导记录(PBR)、根目录、空闲空间管理结构、FCB/inode 表。⚠️分区在它之前、扇区划分与校验码位数属物理格式化。
- 判"归不归文件系统"的判据:这件事跟具体是什么硬件有关吗。 有关的不归——划分扇区归硬件、降低寻道时间归磁盘调度、均衡磨损归 SSD 的 FTL;确定盘块大小归文件系统。
- 提高文件访问速度的四条路都成立:提前读(预测下一块并提前调入)、为文件分配连续的簇(减少寻道)、延迟写(合并多次写、命中缓冲区就不落盘)、磁盘高速缓存(把常用块留在内存)。
这一节在真题里被考过的形式:
三道题,都在考"这件事归谁做"这一类边界判断,没有计算。
- 问文件系统能为温彻斯特硬盘(机械盘)和固态硬盘都提供的功能(2025-32)。答确定盘块大小。⚠️ 另三项各自只对一类硬件有意义:划分扇区归硬件、降低寻道时间对 SSD 无意义(它没有寻道)、实现均衡磨损对机械盘无意义(它不怕擦写次数)。判据就是速记第七条——题干里"为两种盘都提供"这半句,本身就是在要求这个功能与硬件无关。
- 问磁盘逻辑格式化程序所做的工作(2017-29,与目录共享)。答建立文件系统的根目录 + 对保存空闲磁盘块信息的数据结构进行初始化。⚠️ 分区在逻辑格式化之前、确定扇区校验码所占位数属于物理格式化。完整的制盘四步顺序在操作系统引导。
- 问哪些优化方法可以提高文件访问速度(2018-31)。答四条全部:提前读、为文件分配连续的簇、延迟写、采用磁盘高速缓存。⚠️ 唯一可能犹豫的是延迟写——它看起来是"推迟"而不是"加快",但推迟的是落盘,而应用看到的
write立刻就返回了,且多次写同一块最终只产生一次磁盘写。判据是"它减不减少实际的磁盘 I/O 次数或等待时间",四条都减。
复习优先级:必须拿满,全是判据题。 第七条那条"跟硬件有关吗"的判据是本节最有价值的一句, 它同时能解 2025-32 和 2017-29 的一半。第一条的布局顺序要能默写出来, 第四条(inode 区定死)在 inode 已经出现过一次,是同一条结论。
易错:认为划分扇区是文件系统做的。那是硬件——机械盘低级格式化、SSD 由控制器决定。
易错:认为降低寻道时间是文件系统提供的功能。它归磁盘调度,而且 SSD 根本没有寻道。
易错:认为均衡磨损是文件系统的职责。它归 SSD 控制器的 FTL,机械盘不需要。
易错:把分区算进逻辑格式化。分区在它之前;扇区划分与校验码位数属物理格式化。
易错:认为延迟写会拖慢文件访问。它推迟的是落盘,
write立刻返回,且多次写同一块只产生一次磁盘写。
易错:认为超级块只是一堆统计信息。后面所有区域的位置都靠它描述,坏了整个文件系统就废。
易错:认为磁盘有空闲块就一定能建文件。inode 区在格式化时定死,inode 用完就建不了。
教材出处
- 汤小丹《计算机操作系统》印刷版 p234:磁盘索引结点与内存索引结点的字段差别(内存索引结点额外增加索引结点编号、状态、访问计数),是本篇"内存 inode 表存什么"的依据。
- 孙钟秀、费翔林《操作系统教程》(第 6 版)印刷版 p176:系统"为每个用户进程建立一张活动文件表(又称打开文件表)",打开时"将该文件有关的目录信息复制到指定的主存区域",后续访问"无须重复遍历相关子目录路径,而是通过访问活动文件表项来快速获得相应信息"——这正是内存中这几张表存在的理由。
相关知识
硬链接和软链接|外存空闲空间管理|文件元数据与索引节点|文件的操作|文件系统挂载|虚拟文件系统|磁盘