文件的物理结构
这一节回答第 4 章最核心的一个问题:一个文件的第 0 块、第 1 块、第 1000 块,到底放在磁盘的什么地方,操作系统怎么找到它们。
本节是全章计算题的来源,也是与第 3 章内存分页结构最像的一节——“逻辑块号 → 物理块号”的映射思路完全一致,只是把内存页框换成了磁盘块。看清这一层对应关系,后面的三种分配方式就不再是三套孤立的规则。
机制
文件也有”逻辑地址”
磁盘按块(或簇,即若干连续磁盘块的组)为单位读写,文件也因此被划分成等长的逻辑块,从 0 开始编号。用户给出的字节偏移量会先被拆成两部分:
这和内存分页的地址拆分是同一个公式,原因也相同:块(页)是等长的,所以除法与取余能直接完成拆分。
块内偏移在整个转换过程中原样不动,需要”翻译”的只有逻辑块号 → 物理块号。三种分配方式的差别,全部集中在这一步怎么翻译。
连续分配
连续分配要求每个文件在磁盘上占有一组连续的块。 目录项只需记录起始块号和长度,翻译过程是一次加法:
缺点有两条,且都很致命。 其一是文件难以增长:后面紧邻的块可能已被别人占用,此时要么整体搬家,要么无法扩展。其二是产生外部碎片:反复创建删除后,磁盘上散落着许多不够大的空闲片段,可以用紧凑来解决,但代价极高。
链接分配之一:隐式链接
隐式链接把”下一块的块号”存放在每个数据块的内部,像一条单向链表。目录项只记录首块号(有的系统还记末块号)。
优点是彻底消除了外部碎片,且文件扩展极其方便——找一个空闲块,改一下链尾的指针即可。
缺点是无法直接访问。 要读第
链接分配之二:显式链接与 FAT
疑问点:FAT 的具体结构与工作方式
FAT 是什么,具体如何组织与使用。
显式链接的思路只有一句:把散落在各个数据块内部的指针,全部集中到一张表里。 这张表就是文件分配表(FAT, File Allocation Table),一个磁盘(分区)只有一张。
FAT 的结构极其简单:整个分区有多少个簇,FAT 就有多少个表项,第
| 表项内容 | 含义 |
|---|---|
| 一个簇号 | 本簇的下一簇是它 |
EOF | 本簇是文件的最后一簇 |
FREE(通常为 0) | 本簇空闲 |
BAD | 本簇是坏簇,不可使用 |
假设某文件的目录项记录”起始簇 = 7”,而 FAT 中 FAT[7] = 13、FAT[13] = 4、FAT[4] = EOF,那么这个文件占用的簇依次是 7 → 13 → 4,共三簇。
FAT 的关键在于它被整体读入内存。 系统启动时把 FAT 装进内存,此后追链的动作全部在内存中完成,一次磁盘 I/O 都不需要。这一点是它区别于隐式链接的全部价值所在。
FAT12 / FAT16 / FAT32 中的数字指的是 FAT 表项的位数,即能表示多少个簇号:FAT16 的表项 16 位,最多编号
FAT 还兼任空闲块管理:表项为 FREE 的簇就是空闲簇,不需要另设位示图。这一点在 4.3.3 中还会作为一个考点出现。
索引分配
索引分配为每个文件单独建立一张索引表,表中第
翻译过程变成:读索引块 → 取第
问题在于一个索引块可能装不下。 若块大小 4KB、每个地址项 4B,一个索引块只能放 1024 个地址,即最多支持 4MB 的文件。三种解决办法:
① 链接方案——把多个索引块用链表串起来,最后一项指向下一个索引块。缺点是查后面的索引块又退化成顺序查找。
② 多层索引——让第一级索引块的每一项指向一个第二级索引块,如同多级页表。
③ 混合索引——把前两者结合,也是 UNIX 的做法,见下。
UNIX 的混合索引
疑问点:UNIX 混合索引结构的具体组织
UNIX 混合索引结构是怎样组织的。
混合索引的核心思想是:小文件不该为大文件的能力付出代价。
UNIX 的 inode 中含有 13 个地址项 iaddr(0) ~ iaddr(12),分工如下:
iaddr(0)~iaddr(9):10 个直接地址项,直接指向数据块。iaddr(10):一级间接地址项,指向一个索引块,该索引块的每一项再指向数据块。iaddr(11):二级间接地址项,指向一个索引块,其每一项指向一个一级索引块。iaddr(12):三级间接地址项,再多一层。

设块大小
| 层级 | 可寻址块数 | 覆盖的文件大小 |
|---|---|---|
| 直接(10 项) | ||
| 一级间接 | ||
| 二级间接 | ||
| 三级间接 |
这张表就是混合索引全部设计意图的证明:小于 40KB 的文件(绝大多数)完全不用间接索引,一次就能拿到数据块地址;而一旦需要,规模能一路撑到 TB 级。用极少数大文件的额外开销,换取绝大多数小文件的零开销。
判断偏移量落在哪一级
这是计算题的固定套路,分三步:
① 求逻辑块号
② 判断
③ 算索引块内的下标。 一级间接下标为
访问磁盘次数(假定 inode 已在内存):直接地址 1 次,一级间接 2 次,二级间接 3 次,三级间接 4 次。规律是每多一级间接就多读一个索引块。若 inode 不在内存,每一项都要再加 1。
边界
显式链接为什么支持随机访问
疑问点:显式链接支持直接访问的原因
显式链接为什么支持直接访问。
因为链在内存里,走链不花磁盘 I/O。
隐式链接和显式链接在逻辑上做的是同一件事——顺着链走
- 隐式链接:指针在数据块内部,走一步就得读一次磁盘。走
步 = 次磁盘 I/O。 - 显式链接:指针在内存的 FAT 里,走一步只是一次内存访问。走
步 = 次内存访问 + 最后读目标块的 1 次磁盘 I/O。
磁盘访问比内存访问慢约十万倍,所以这
但必须守住一条边界:显式链接的随机访问不是索引分配那种真正的直接定位。 FAT 仍然要在内存中走
显式链接与索引分配的区别
疑问点:显式链接与索引分配的差异
显式链接和索引分配的区别是什么。
两者都把地址信息从数据块里搬了出来,区别在于搬到哪里、按什么组织:
① 表的数量和归属不同。 FAT 全盘只有一张,为整个分区的所有文件服务;索引块是一个文件一张(甚至多张),只服务于这一个文件。
② 表项的语义不同。 FAT 第
③ 定位方式不同。 FAT 要追链(
④ 空间开销的分布不同。 FAT 的大小只与分区大小有关,与文件多少、大小无关——哪怕分区上只有一个文件,FAT 也是满的;索引块的开销与文件数量和大小成正比,小文件多时索引块的浪费很明显。
⑤ 能否兼管空闲块。 FAT 天然可以(表项为 FREE 即空闲);索引分配不行,必须另设位示图或空闲链表。
文件中间插入一块,哪种方式 I/O 最多
疑问点:在文件中增加一块时磁盘 I/O 次数最多的分配方式
某 500 个盘块的文件的目录项已调入内存(索引分配,索引块也在内存中),若需要在文件中增加一块,下列分配方式中磁盘 I/O 次数最多的是( )。 A. 连续分配 B. 隐式链接分配 C. 显式链接分配 D. 索引分配
答案 A。
题干的关键词是”在文件中增加一块”,即中间插入,而不是末尾追加。
连续分配下,插入位置之后的所有盘块必须整体向后移动一块才能腾出位置。500 个盘块的文件,最坏情况下要读出并写回数百个块,磁盘 I/O 数以百计。
其余三种都不需要搬动任何数据块:隐式链接改前后两个块内的指针,显式链接改两个 FAT 表项(在内存中),索引分配改索引表中的若干项(索引块也已在内存)。它们的开销都是常数级的。
这道题必须与”末尾追加”严格区分开。 若改为在文件末尾追加一块,结论会变:连续分配若后面正好有空闲块则只需 1 次写,反而是隐式链接最慢——只知道首块号时,必须顺链读完 500 块才能找到链尾。
所以看到”增加一块”,第一件事是找题干里说的是”中间”还是”末尾”。
FAT 的三道计算题
以下三问同源,条件相同:磁盘块 4KB,一簇 = 2 个磁盘块,以簇为分配单位,最大文件长度 512MB,FAT 表项仅存放簇号。
① 系统支持的最大文件块数。
问的是磁盘块数,直接用最大长度除以磁盘块大小:
② FAT 表项至少多少位。
最大文件占
③ FAT 表占多少空间。
另外要分清**“表项位数”和”FAT 总大小”:16 位是每一个表项的宽度,128KB 是整张表**的大小,两者相差一个”表项个数”的因子。
单个文件的最大长度与 inode 总数无关
这一条在 4.1.2 已经论证过,这里给出计算侧的说法:最大文件长度
文件控制信息里存什么物理地址信息
同一个”文件的物理位置”字段,在不同分配方式下装的东西完全不同,这是判断题的常见落点:
连续分配记起始块号 + 长度;隐式链接记首块号;显式链接记起始簇号(后续靠 FAT);索引分配记索引块地址;混合索引把直接地址与各级间接地址项一起放在 inode 里。
不要以为”inode 里总是列出了文件的全部数据块地址”——只有小文件才如此,大文件的 inode 里存的是索引块的地址,真正的数据块地址在索引块中。
对照速查
| 连续分配 | 隐式链接 | 显式链接(FAT) | 索引分配 | |
|---|---|---|---|---|
| 地址信息在哪 | 目录项 | 数据块内部 | 内存中的 FAT | 索引块 |
| 随机访问 | 最快, | 不支持 | 支持(内存追链 | 支持, |
| 外部碎片 | 有 | 无 | 无 | 无 |
| 文件扩展 | 困难 | 容易 | 容易 | 容易 |
| 能否管空闲块 | — | 否 | 能 | 否 |
| 主要缺点 | 碎片、难增长 | 必须顺链,指针坏则后续全丢 | FAT 占内存,大小随分区增长 | 小文件索引块浪费 |
| FAT 表项取值 | 含义 |
|---|---|
| 簇号 | 下一簇 |
EOF | 文件末簇 |
FREE | 空闲簇(可用于空闲块管理) |
BAD | 坏簇 |
| 混合索引( | 块数 | 覆盖大小 | 访问磁盘次数 |
|---|---|---|---|
| 直接 | 10 | 40KB | 1 |
| 一级间接 | 1024 | 4MB | 2 |
| 二级间接 | 4GB | 3 | |
| 三级间接 | 4TB | 4 |
| 题眼 | 结论 |
|---|---|
| ”在文件中间增加一块” | 连续分配 I/O 最多 |
| ”在文件末尾追加一块” | 隐式链接可能最慢(要顺链找尾) |
| “FAT 表项仅存簇号” | 先算最大簇数 → 定表项位数 |
| ”最大文件块数” | 用最大长度 ÷ 磁盘块大小(不是簇) |
| “与单个文件长度无关” | inode 总数 |
考点
- 逻辑块号 → 物理块号的翻译方式,是三种分配方式的唯一区别
- 连续分配是唯一
定位的,但有外部碎片、难增长 - 隐式链接不支持随机访问;指针在数据块内部
- 显式链接支持随机访问的原因是 FAT 在内存,但仍是追链而非直取
- FAT 全盘一张、按物理簇号索引、可兼管空闲块;索引块一文件一张、按逻辑块号索引
- FAT12/16/32 的数字是表项位数,决定能管多大分区
- 混合索引的意图:小文件零间接开销,大文件仍能到 TB 级
- 最大文件大小
;访问次数每多一级加 1 - “中间插入”选连续分配;“末尾追加”结论相反
- FAT 计算题先统一单位;表项位数 ≠ FAT 总大小
链接
- 🏠 返回总览:操作系统第 4 章:文件管理总览
- ⬅️ 上一节:4.1.4 文件的逻辑结构
- ➡️ 下一节:4.1.6 文件保护
- 🔗 与内存分页的地址转换对照,见 3.1.3 基本分页存储管理
- 🔗 FAT 兼管空闲块,见 4.3.3 文件存储空间管理
- 📖 名词库:第 4 章名词库