做《计算机操作系统(第四版)》这套习题整理,到第七篇东西是最碎的,但也是每次考试必出大题的区域。很多读者私信我,说刷到文件管理章节就明显卡壳,网上流传的答案要么只给结论不给过程,要么把混合索引、位示图、FAT 这类计算题写得跟天书一样。这篇我把第七部分的高频考点重新捋一遍,不光是给答案,而是把每一道代表性习题的手算过程完整走下来,最后还会放一份我批改作业时积累的典型错误清单。内容不局限于某一类读者,期末冲刺、考研复习、自学补课都能直接用,基础弱一点的建议配合教材第七章边看边推。
1. 先搞清楚"第七部分"到底覆盖哪些章
1.1 章节对应的真实位置
网上流传的《计算机操作系统(第四版)》习题答案,不同版本编号不太一样。我这个系列是按考点热度来排的,前六篇处理了进程、调度、死锁、内存、虚拟存储和输入输出,第七部分自然落到全书里最讲究"数据结构与计算"的文件管理,外加一批跨章节的综合题。
具体对应教材内容大致是:
- 文件系统的层次模型与基本概念:文件、目录、文件的逻辑结构和物理结构
- 目录管理与文件控制块(FCB)
- 文件的物理结构:连续、链接(FAT)、索引(混合索引)
- 空闲存储空间管理:空闲表法、空闲链表法、位示图法、成组链接法
- 文件系统的性能:磁盘调度、文件保护、文件系统的一致性
- 这一章后半段常和前面章节串考:页面置换、银行家算法、信号量机制
如果你手边的答案目录把"第七部分"标成"文件管理",那基本就是这批题。我不太建议死记章节号,因为各版本习题册的拆分方式不同,重要的是认准考点本身。
1.2 高频考点和它的出题位置
统计了近几年的考试题和常见习题册,第七部分的分值分布大致有个规律:
| 考点 | 常见题型 | 难度 | 出现频率 |
|---|---|---|---|
| 混合索引最大文件长度 | 计算题 | 中 | 极高 |
| FAT 表容量计算 | 计算题 | 低 | 高 |
| 位示图盘块换算 | 计算题 | 低 | 极高 |
| 目录检索平均访盘次数 | 计算与应用题 | 中 | 中 |
| 页面置换算法缺页统计 | 表格填答 | 中 | 极高 |
| 银行家算法安全性判断 | 计算题 | 中高 | 极高 |
| 生产者-消费者信号量 | 程序填空或写代码 | 中 | 高 |
你会发现一个现象:文件管理这一章本身的计算题不算难,但考生普遍丢分在"算错单位"和"不写推导过程"上。后面的批改笔记里我会专门讲这两个问题,现在先按题型把必考题过一遍。
2. 文件管理三道必考题的手算全程
2.1 混合索引:最大文件长度到底怎么加
这道题是文件物理结构里面最经典的,几乎每个版本答案都有,但讲清楚的不多。
题目一般这样给:文件系统一个物理块大小为 1KB,一个盘块号占 4B,采用 UNIX 系统的混合索引结构,其中直接地址有 10 个,一级间接、二级间接、三级间接各一个,问单个文件最大为多大。
先算一级间接能指向多少块:
一个索引块大小是 1KB,每个地址项 4B,所以每块能存放的地址项数是:
1024 / 4 = 256 个
这意味着:
- 10 个直接地址能存 10 块数据,大小 10 × 1KB = 10KB
- 一级间接能存 256 个盘块号,对应 256 × 1KB = 256KB
- 二级间接:256 × 256 = 65536 块,对应 65536 × 1KB = 64MB
- 三级间接:256 × 256 × 256 = 16777216 块,对应 16777216 × 1KB = 16GB
最后把四段加起来:
10KB + 256KB + 64MB + 16GB
所以答案是:单个文件最大约 16GB 量级,精确值为 16GB + 64MB + 256KB + 10KB。
这里最容易犯的错,是把直接地址那 10 块漏掉,只算三级间接。漏掉之后答案就成了"16GB",看起来差不多,但过程分没了,而且如果题目把数字改小一点,比如直接地址只有 5 个,漏加会导致最终结果完全不对。
另外我建议做题前先确认块大小和地址项大小。有的题目把物理块设为 4KB,地址项还是 4B,那么一个索引块能放 1024 个地址项,一级间接对应的容量直接变成 4MB。我见过同一道考研题换了块大小后一堆人套错公式,关键就是不看假设条件。
2.2 位示图:盘块号、字号、位号的换算
位示图的题有固定的套路,弄懂了非常白给。
标准题目:某磁盘组共有 10000 个盘块,每个盘块 1KB,系统用位示图管理空闲盘块,字长 32 位,问位示图需要多少个字?占用多少字节?
计算方式:
10000 / 32 = 312.5
所以需要 313 个字,其中最后一个字只用了 16 位,剩下 16 位闲置。占用字节数:
313 × 4 = 1252B
注意,如果题目问的是"为了管理这些盘块位示图需要多少字节",千万不要用 10000 位直接除以 8 再去取整,虽然数值上差不多,但步骤里体现不出"字"的概念,改一个数字就可能错。我批改时经常看到有人写成 1250B,这是把 10000/8=1250 直接得了。严格按"字数 × 字长"来算才是标准做法。
位示图的换算题还会换个方向考:给出字号 i、位号 j,求盘块号 b。不同教材约定不同,我按最常见约定写:
如果字号和位号都从 1 开始编号,盘块号也从 1 开始编号,则:
盘块号 = (字号 - 1) × 字长 + (位号 - 1) + 1
反过来的计算:
字号 = (盘块号 - 1) / 字长 的商加 1 位号 = (盘块号 - 1) / 字长 的余数加 1
如果改为从 0 开始编号,就把整个公式里的加减 1 全部去掉。做题时先看题目开头有没有"从 0 开始"或"从 1 开始"的说明,很多丢分不是因为不会,是根本没注意编号约定。
2.3 FAT 表容量:记住公式就能拿分
FAT 也就是文件分配表,考察的核心只有一个公式:
FAT 表大小 = 簇数 × 每个 FAT 表项占用的字节数
举一个常见模拟题:某磁盘容量 1GB,每簇大小 4KB,假设 FAT 表项占 2B,单张 FAT 表有多少字节?若系统保留两份 FAT,共需要多少字节?
先算簇数:
1GB = 1024MB = 1048576KB 1048576 / 4 = 262144 簇
单张 FAT:
262144 × 2 = 524288B = 512KB
两份 FAT 共:
524288 × 2 = 1048576B = 1MB
这个例子有个真实背景值得提醒:FAT16 的表项最大只能表示 65536 个簇,所以 1GB 磁盘配 4KB 簇其实超出了 FAT16 的能力范围,现实中会用 FAT32。命题人如果出这类题,通常会把"表项占 2B"当成简化条件,你按公式算没问题,但答题时可以加一句"此处忽略 FAT16 的簇数上限,按题目给定条件计算",显得你懂原理。
3. 跨章节综合题:页码置换、银行家、信号量这样答不丢分
3.1 页面置换:一页一页写出来,别跳步
第七部分经常串进虚拟存储的页面置换题,因为文件系统涉及 I/O 访问,考试爱把两者揉在一起。最常考的是 OPT、FIFO、LRU 三种算法。
题目一般给一个页面访问序列和一个物理块数,比如:
访问序列:7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 物理块数:3
我在辅导时永远要求学生一行一行列状态,不许心算。因为心算很容易漏掉"某页是否已在内存"的判断。三个算法的缺页次数分别是:
| 算法 | 缺页次数 |
|---|---|
| OPT | 7 |
| FIFO | 15 |
| LRU | 12 |
不少同学第一次算 OPT 会得到 8 或 9,问题多半出在某个替换时刻的"未来最远访问"选错了。我把 OPT 的关键决策点说一下:
第一次缺页发生在访问 4 时,此时内存里是 2、0、3,未来访问顺序里 2 在第 9 次出现,0 在第 11 次出现,3 在第 10 次出现,所以要淘汰 0,因为 0 是下次使用最晚的。注意是在所有在内存的页中比较"下次访问位置",不是比较"最近是否用过"。
LRU 的答案 12 次是很多教材的标准结论,FIFO 是 15 次。考试如果要求写出"置换序列",每一步淘汰谁要标清楚。只写缺页次数通常只能拿一半过程分。
3.2 银行家算法:先算 Available,再找安全序列
银行家算法在"进程管理"内容里叫死锁避免,但第七部分的综合卷特别喜欢把它和文件系统的资源管理一起考。我给出我常用的一组数据,这套数据配平过,适合当练习模板。
系统共有 A、B、C 三类资源,数量分别为 10、5、7。五个进程 P0 到 P4 的分配情况如下:
| 进程 | 已分配 Allocation | 还需要 Need |
|---|---|---|
| P0 | (0, 1, 0) | (7, 4, 3) |
| P1 | (2, 0, 0) | (1, 2, 2) |
| P2 | (3, 0, 2) | (6, 0, 0) |
| P3 | (2, 1, 1) | (0, 1, 1) |
| P4 | (0, 0, 2) | (4, 3, 1) |
先求总已分配:
A: 0+2+3+2+0 = 7 B: 1+0+0+1+0 = 2 C: 0+0+2+1+2 = 5
所以 Available = (10-7, 5-2, 7-5) = (3, 3, 2)
找一个安全序列的过程:
- P1 的 Need (1,2,2) ≤ (3,3,2),满足,P1 执行完归还 Allocation (2,0,0),Available 变成 (5,3,2)
- P3 的 Need (0,1,1) ≤ (5,3,2),满足,归还 (2,1,1),Available 变成 (7,4,3)
- P4 的 Need (4,3,1) ≤ (7,4,3),满足,归还 (0,0,2),Available 变成 (7,4,5)
- P0 的 Need (7,4,3) ≤ (7,4,5),满足,归还 (0,1,0),Available 变成 (7,5,5)
- P2 的 Need (6,0,0) ≤ (7,5,5),满足,归还 (3,0,2),Available 变成 (10,5,7)
安全序列是 P1 → P3 → P4 → P0 → P2,所以当前状态安全。
这个题还喜欢追加一问:如果此时 P1 再请求 (1, 0, 2),能否立即分配?
判断三步:
- Request ≤ Need?(1,0,2) ≤ (1,2,2),成立
- Request ≤ Available?(1,0,2) ≤ (3,3,2),成立
- 试探分配并检查安全性:Available 变成 (2,3,0),P1 的 Allocation 变成 (3,0,2),Need 变成 (0,2,0)
再找安全序列:P1 可先完成,归还后 Available 变成 (5,3,2),接着 P3、P4、P0、P2 都能陆续完成,仍存在安全序列。因此可以立即分配。
这个追问极容易丢分,因为很多人只判断满不满足 Request ≤ Available,就写"能分配",完全忘了要证明分配后系统依然安全。考场上一项一项写,哪怕结果不对也能拿步骤分。
3.3 生产者-消费者:信号量初值写错等于全错
文件系统里有缓冲池的概念,配合进程同步考"生产者-消费者"是第七部分综合题的保留节目。标准的信号量解法如下:
semaphore empty = n; // 空闲缓冲区个数 semaphore full = 0; // 已装满缓冲区个数 semaphore mutex = 1; // 缓冲区互斥 void producer() { while (true) { produce(); wait(empty); wait(mutex); add_to_buffer(); signal(mutex); signal(full); } } void consumer() { while (true) { wait(full); wait(mutex); remove_from_buffer(); signal(mutex); signal(empty); consume(); } }注意几个常考点:
- empty 初值是缓冲区大小 n,不是 0;full 初值是 0,不是 n
- mutex 的值只能为 1 或 0,P/V 必须成对,不能少
- 两个 wait 的顺序不能颠倒。如果先 wait(mutex) 再 wait(empty),在缓冲区满时生产者拿着锁去等空位,消费者又拿不到锁去释放空位,直接死锁
还有一种改法是把消费者里的两个 wait 也换顺序,同样会在缓冲区空时让消费者拿着锁等 full 信号,导致生产者无法释放。正确答案永远是"先操作资源信号量,再操作互斥信号量"。这个顺序如果考试填程序填空,写反了直接零分,因为这不是逻辑等价,而是死锁。
4. 批改第七部分作业时最常见的六个错误
4.1 混合索引漏加直接地址
开头已经说过,不多重复。这里再补一句:还有人在计算一级间接时,把 1024 / 4 算成 250。1024 ÷ 4 = 256,建议算完自己乘回去验证下:256 × 4 = 1024,不会错。
4.2 位示图换算不区分编号起点
位示图题最坑的地方不是公式本身,而是 0 起点和 1 起点的差异。教材示例常从 1 开始,但有些习题直接给数组下标从 0 开始。我教学生的办法是:读完题先在草稿纸上写一行"字号=1 起始 / 位号=1 起始"或"从 0 开始",然后才动笔。这一步花十秒钟,能避免最冤的失分。
4.3 页面置换只写缺页次数,不写状态过程
考试里"求缺页次数"四个字不等于"只要数字"。我在批改时见过的典型丢分卷是:只写了"缺页 12 次",没有任何中间状态,而前面有个步骤算错了,数字差一个,过程分全没。哪怕题目没要求"写出置换过程",我依然建议在草稿纸上列好,最后誊写时把关键状态画成简表,既能自查也方便阅卷。
4.4 银行家算法只判断安全,不回应请求
前面提过,再强调一次。加了"此时某进程请求 xx,能否分配"的题,完整答题逻辑是:先检查请求合法性,再试探分配,再判断安全性,再给结论。少任何一环都会被扣分,尤其不能省略试探分配后的 Available 变化。宁可让答题多写三步,不要为了省字数丢掉大分。
4.5 信号量初始值调错
empty 和 full 的初始值是最直观的错误来源。一张小型对比表帮大家记住:
| 信号量 | 含义 | 初始值 |
|---|---|---|
| empty | 空闲缓冲区的数量 | 缓冲区总大小 n |
| full | 已占用的缓冲区数量 | 0 |
| mutex | 缓冲区访问互斥 | 1 |
如果题目改为多个生产者和多个消费者,mutex 也只设一个,不要给每个消费者单独设 mutex,那是把"数据缓冲区互斥"和"消费者身份唯一"混为一谈了。
4.6 文件目录检索的"平均"和"最大"不分
目录相关小题容易被忽略。比如顺序目录结构,文件目录项按顺序排列,找一个文件:
- 最大访问次数是目录项总数
- 平均访问次数约是目录项总数的一半
很多答案把平均访盘算成"恰好 N/2"当精确公式,实际应说明"若无频率权重,近似 N/2;若按访问频率加权,要另算"。考试若给了各个文件访问频率,记得用加权平均,别只会拿 N/2 硬套。
5. 最后一张速查表:把碎片考点一次性压平
第七部分信息量大,考前临时翻书容易乱。我把最常用的一张速查表放在这里,配合教材复习时直接在笔记本上重抄一遍,比来回翻页高效。
5.1 三类算法一表对照
| 类别 | 算法 | 核心特征 | 一句话记忆 |
|---|---|---|---|
| 处理机调度 | FCFS | 先来先服务 | 排队的逻辑 |
| 处理机调度 | SJF / SPF | 短作业优先 | 平均等待时间最短,但可能饿死长作业 |
| 处理机调度 | HRRN | 高响应比优先 | 响应比 = (等待时间 + 要求服务时间) / 要求服务时间 |
| 处理机调度 | 时间片轮转 | 时间片轮流给 | 时间片太大会退化成 FCFS |
| 页面置换 | OPT | 淘汰未来最远使用的页 | 理想,无法真正实现,仅作参照 |
| 页面置换 | FIFO | 淘汰最早进入的页 | 可能出现 Belady 异常 |
| 页面置换 | LRU | 淘汰最久未使用的页 | 用历史近似未来,开销较大 |
| 磁盘调度 | SSTF | 优先离当前磁道最近 | 可能饿死远端请求 |
| 磁盘调度 | SCAN | 电梯算法,单向扫描 | 类似电梯先到顶再回底 |
| 磁盘调度 | C-SCAN | 循环扫描,只单向服务 | 回程不处理请求 |
5.2 文件物理结构三方案对比
| 结构 | 优点 | 缺点 | 典型计算 |
|---|---|---|---|
| 连续结构 | 顺序访问快,支持随机访问 | 需要连续空间,易碎片,文件难扩充 | 起始块号 + 长度 |
| 链接结构(隐式) | 空间利用率高,易于扩充 | 不支持直接随机访问,指针占空间 | 遍历指针次数 |
| 索引结构 | 支持随机访问,便于扩充 | 索引块额外空间,小文件内部碎片 | 混合索引最大长度 |
| FAT(显式链接) | 链接表的改进,查表即可随机访问 | FAT 本身占空间 | FAT 容量 = 簇数 × 表项字节数 |
5.3 死锁四条件和处理策略
| 必要条件 | 处理策略方向 |
|---|---|
| 互斥 | 一般难破坏,只能尽量让资源可共享 |
| 持有并等待 | 资源一次性分配,进程运行前申请全部资源 |
| 不可剥夺 | 允许剥夺资源,如抢占式调度 |
| 循环等待 | 资源有序分配,按编号顺序申请 |
结合第七部分的文件系统内容,建议额外记忆一条:打开文件表、活跃文件表这些结构用于管理进程与文件的关联,考试若出"文件共享与保护"的小题,大概率会问你软链接和硬链接的区别。硬链接指向同一个 inode 或文件控制块,软链接是一个独立文件记录目标路径;删除原始文件时,硬链接不受影响,软链接失效。这个点属于第七部分的小考点,看着不值钱,但填空选择题常出。
我把这套内容整理完后的个人建议是:第七部分不要追求"背完所有答案",而是把上面每道计算题的推导步骤写一遍,直到不看答案能独立推出为止。你动手推一遍混合索引加总、推一遍银行家安全序列,记忆深度远胜于翻看十遍答案。
如果你刷这组题时还有哪一步卡住,可以把具体题目拿来一起讨论。这个系列的下一部分我打算挑几道和"文件系统性能优化"相关的进阶题,比如磁盘寻道时间计算和文件系统一致性检查,到时候再继续拆。