总体结论
这些卷子的重点非常稳定。几乎每年都会围绕下面几类题展开:
- UNIX 进程与系统调用:
fork、wait、sleep、open、read、write、dup、管道、I/O 重定向、文件描述符和打开文件表。 - 作业/进程调度与内存管理混合题:FCFS、SJF、优先级、RR、多级反馈队列,常和主存分配、设备静态分配一起考平均周转时间。
- 死锁:银行家算法、安全序列、资源请求能否满足、死锁检测、死锁必要条件。
- 请求分页:页表规模、二级页表地址划分、反置页表、页表项字段、缺页异常、NRU/LFU/LRU/Aging/Clock/FIFO。
- UNIX 文件系统:inode 直接/间接索引、目录项、
open内核路径、硬链接/软链接、文件描述符复制、逻辑块到物理块、读写物理块数。 - 磁盘调度与同步编程:FCFS/SSTF/SCAN/C-SCAN/电梯调度、读者写者、管程、信号量、匿名管道。
复习优先级建议:
| 优先级 | 内容 | 原因 |
|---|---|---|
| 必拿 | fork 进程树、管道重定向、文件描述符共享 |
2016、2017、2018、2020、2021、2022 都考 |
| 必拿 | 银行家算法/死锁检测 | 2016、2017、2018、2019、2020、2021、2022 都考 |
| 必拿 | 请求分页和页面置换 | 2016、2017、2018、2020、2021、2022 都考 |
| 必拿 | inode 索引计算、open/read/write/dup/link |
2016、2017、2018、2020、2021、2022 都考 |
| 高频 | 作业调度、平均周转时间、RR 平分 CPU | 2016、2017、2018、2020、2021、2022 都考 |
| 高频 | 磁盘调度与容量/旋转延迟 | 2016、2017、2018、2019、2020、2021、2022 都考 |
| 高频 | 管程/信号量编程 | 每年第二大题常考 |
一、进程调度
1. 基本指标
常用时间定义:
- 到达时间:作业/进程到达系统或就绪队列的时间。
- 开始时间:第一次获得 CPU 或进入主存创建进程的时间,题目要看语境。
- 完成时间:运行结束时间。
- 周转时间 = 完成时间 - 到达时间。
- 带权周转时间 = 周转时间 / 实际运行时间。
- 平均周转时间 = 所有作业周转时间之和 / 作业数。
- 平均带权周转时间 = 所有带权周转时间之和 / 作业数。
易错点:
- “进入主存时间”和“开始运行时间”不是同一个概念。多道程序设计系统中,作业进入主存后可能与其他作业 RR 平分 CPU。
- RR 题如果说“时间片远小于各作业运行时间”,通常表示多个驻留作业近似平均分享 CPU。
- 作业调度决定谁进入内存;进程调度决定内存中的进程谁占 CPU。卷子常把两层调度混在一题里。
2. FCFS
先来先服务,按到达顺序运行。
特点:
- 实现简单。
- 对长作业有利,对短作业不利。
- 容易产生 convoy effect,短作业排在长作业后面会等待很久。
计算套路:
- 按到达时间排序。
- 当前时间小于下一作业到达时间时,CPU 空闲到该作业到达。
- 完成时间逐个累加运行时间。
- 计算周转时间和带权周转时间。
3. SJF/SPF
短作业优先,选择估计运行时间最短的作业。
特点:
- 在所有作业同时到达、运行时间已知时,平均周转时间最短。
- 可能导致长作业饥饿。
- 实际系统难点是预测运行时间。
证明思路:
若两个相邻作业运行时间分别为 a 和 b,且 a > b。把顺序从 a,b 交换为 b,a,后续作业完成时间不变,这两个作业总等待/周转时间减少 a-b。不断交换逆序长短作业,可得按运行时间升序时平均周转时间最小。
4. RR
时间片轮转,适合分时系统。
特点:
- 公平,响应时间较好。
- 时间片过短,调度开销大;时间片过长,退化为 FCFS。
- 考题常问调度开销百分比。
例:时钟中断每秒 100 次,每次中断处理 1ms;RR 以 10 个时钟中断为 1 个时间片;一次调度 2ms,分派 CPU 1ms。时间片长度 10 * 10ms = 100ms,每个时间片内开销为 10 * 1 + 2 + 1 = 13ms,CPU 调度相关开销为 13%。
5. 优先级调度
注意题目会说明“优先数越小优先级越高”或相反。不要按常识假设。
抢占式:
- 高优先级进程到达后可抢占 CPU。
- 响应紧急任务好。
- 调度频繁,开销大,低优先级可能饥饿。
非抢占式:
- 已运行进程不主动让出 CPU 前不会被抢占。
- 开销较小。
- 高优先级任务可能等待长作业结束。
6. MLFQ
多级反馈队列的核心思想:
- 多个优先级队列,高优先级队列时间片短,低优先级队列时间片长。
- 新进程通常先进高优先级队列。
- 用完时间片仍未结束则降级。
- I/O 密集型进程经常阻塞并让出 CPU,容易保持较高优先级;CPU 密集型进程会逐步降级。
- 为避免饥饿,需要周期性提升优先级或 aging。
答题要点:
- 它是对进程行为的动态预测:过去经常很快让出 CPU 的进程更可能是 I/O 密集型,应给予较好响应。
- 设计关键是预测进程行为和避免长期饥饿。
二、请求分页与页面置换
1. 地址划分与页表大小
基本公式:
- 页内偏移位数 =
log2(页面大小)。 - 虚页号位数 = 逻辑地址位数 - 页内偏移位数。
- 一级页表项数 = 逻辑地址空间 / 页面大小 =
2^虚页号位数。 - 一级页表最大大小 = 页表项数 * 页表项大小。
- 页框号位数 =
log2(物理内存 / 页面大小)。
二级页表划分:
- 每个页表页能放的页表项数 = 页面大小 / 页表项大小。
- 页表页内索引位数 =
log2(每页表项数)。 - 页目录位数 = 虚页号位数 - 页表页内索引位数。
常见例子:
- 32 位逻辑地址,4KB 页面,4B 页表项:偏移 12 位;一个页表页有
4096/4 = 1024 = 2^10项;二级页表为10 位页目录 + 10 位页表页索引 + 12 位偏移。 - 32 位逻辑地址,1KB 页面,4B 页表项:偏移 10 位;一个页表页有
1024/4 = 256 = 2^8项;虚页号 22 位,所以二级页表为14 位页目录 + 8 位页表页索引 + 10 位偏移。 - 32 位逻辑地址,2KB 页面,4B 页表项:偏移 11 位;一个页表页有
2048/4 = 512 = 2^9项;二级页表为12 位页目录 + 9 位页表页索引 + 11 位偏移。
多级页表优缺点:
- 优点:页表不需要连续存放;没有使用的虚拟地址范围不必分配页表页,节省内存。
- 缺点:地址转换需要多次访存,若无 TLB 会明显变慢。
反置页表:
- 表项数按物理页框数算:物理内存 / 页面大小。
- 表项至少要包含进程号和虚页号,用来说明该物理页框属于哪个进程的哪个虚页。
- 优点:全系统维护一张与物理内存大小相关的表,节省内存。
- 缺点:地址转换查找复杂;未调入内存的页面仍需其他结构记录,缺页处理可能更慢。
2. 页表项字段
常考字段:
- 页框号:该页在物理内存中的位置。
- 存在位/驻留位/有效位:是否在内存中,不在则触发缺页异常。
- 访问位/引用位 R:最近是否被访问,常由硬件置 1,由 OS 周期性清 0。
- 修改位/脏位 W/M:是否被写过,脏页淘汰前必须写回磁盘。
- 保护位:读/写/执行权限。
- 锁定位:某些关键页面暂时不能被替换,2022 卷在 CALL 指令多次缺页中考过。
- 外存地址:不在内存时页面所在的磁盘位置。
易错点:
- R=0 且 W=1 是可能的:页面以前被写过,尚未写回磁盘;之后 OS 清零了 R 位,但不会因此清零 W 位。
- 写访问一定会置 R 和 W;读访问只置 R。
- 脏页不是不能淘汰,而是淘汰成本更高,需要写回。
3. 缺页异常处理
标准流程:
- CPU 访问虚拟地址,查页表/TLB。
- 有效位为 0,触发缺页异常,陷入内核。
- OS 检查地址是否合法、权限是否允许。
- 找空闲页框;若没有空闲页框,运行页面置换算法选牺牲页。
- 若牺牲页是脏页,先写回磁盘。
- 从外存调入目标页,更新页表项。
- 恢复被中断指令,重新执行。
4. 页面置换算法
FIFO:
- 淘汰最早进入内存的页。
- 实现简单。
- 可能有 Belady 异常。
LRU:
- 淘汰最长时间未被访问的页。
- 理论效果好,但精确实现代价大,需要维护全序访问历史或特殊硬件。
- 常用近似算法:NRU、Clock、Aging、NFU。
NRU:
- 根据 R/M 位分类。
- 优先淘汰
(R=0, M=0);其次(0,1);再(1,0);最后(1,1)。 - 周期性清 R 位,才有“最近未使用”的信息。
Clock:
- FIFO 环形队列 + R 位。
- 指针扫描;遇到 R=1 清 0 并跳过;遇到 R=0 淘汰。
- 增强版 Clock 会结合 M 位,优先干净页。
NFU:
- 每个页面维护计数器,每次时钟中断把 R 位加到计数器。
- 淘汰计数最小者。
- 缺点:早期频繁访问的页面即使后来不用,计数仍很大。
Aging:
- 每个页面维护 n 位寄存器。
- 每次时钟中断右移一位,把当前 R 位放到最高位,然后清 R。
- 寄存器值越小,越久未使用,优先淘汰。
- 要接近 LRU:采样周期要合适,寄存器位数要足够,且每次采样后清 R 位。
OPT:
- 淘汰未来最长时间不会被访问的页。
- 实际不可实现,但可作为评价其他算法的理论下界。
5. 颠簸与工作集
颠簸:系统频繁缺页,大量时间用于换入换出,CPU 利用率下降。
避免条件:
- 同时运行进程的工作集总大小不能超过可用物理内存。
- 页面分配不能过少。
- 页面置换算法应利用局部性,减少不必要淘汰。
三、死锁与银行家算法
1. 死锁四个必要条件
- 互斥:资源一次只能被一个进程使用。
- 占有并等待:进程已占有资源,同时还等待其他资源。
- 不可剥夺:资源不能被强制抢走。
- 循环等待:存在进程等待环。
破坏策略:
- 静态分配所有资源:破坏“占有并等待”。
- 资源有序申请:破坏“循环等待”。
- 可抢占资源:破坏“不可剥夺”。
2. 银行家算法
常用矩阵:
Available:当前可用资源。Max或Claim:最大需求。Allocation:已分配。Need = Max - Allocation:尚需资源。
安全性检测:
Work = Available。Finish[i] = false。- 找一个
Finish[i] == false且Need[i] <= Work的进程。 - 假设它能完成,令
Work = Work + Allocation[i],Finish[i] = true,加入安全序列。 - 重复直到所有进程完成,或找不到可完成进程。
- 全部完成则安全;否则不安全。
资源请求判断:
- 检查
Request[i] <= Need[i],否则超过最大声明,拒绝。 - 检查
Request[i] <= Available,否则暂不能分配。 - 试分配:
Available -= Request[i]Allocation[i] += Request[i]Need[i] -= Request[i]
- 再做安全性检测。
- 试分配后安全才真正分配;否则回滚并拒绝。
易错点:
- “不安全”不等于“已经死锁”。不安全表示未来可能死锁。
- 死锁检测用的是当前
Request,银行家算法用的是最大需求Max/Claim和Need。 - 题目中
Claim有时表示最大需求,有时表头会同时给Request。先看题干定义。 - 向量比较是逐项比较,不能只比较总数。
3. 死锁检测
检测算法通常用当前请求矩阵:
Work = Available。- 没有资源分配的进程可直接
Finish=true,因为它不参与死锁。 - 找
Request[i] <= Work的进程,假设它完成并释放资源。 - 最后仍
Finish=false的进程就是死锁进程。
资源分配图:
- 有环不一定死锁,若每类资源多个实例,需要继续检测。
- 若每类资源只有一个实例,有环就是死锁。
四、进程管理与系统调用
1. API 与系统调用
系统调用:
- OS 提供给用户程序进入内核态请求服务的接口。
- 一定会陷入内核态。
- 例:
fork、exec、wait、open、read、write、close、dup。
API 函数:
- 程序库提供的接口。
- 可能直接在用户态完成,也可能封装一个或多个系统调用。
- 例:
printf是 C 库函数,可能最终触发write;getpid可封装系统调用。
直接使用系统调用的弊端:
- 代码复杂,可读性差。
- 平台差异大,可移植性差。
- 需要自己处理更多细节和错误码。
2. fork
核心语义:
- 调用一次,返回两次。
- 父进程返回子进程 pid。
- 子进程返回 0。
- 失败返回负数。
- 父子进程拥有独立地址空间,普通变量互不影响。
- 文件描述符表会复制,但指向同一个系统打开文件表项,因此共享文件偏移量。
进程数计算:
- 遇到无条件
fork(),当前已有多少个进程,就会新增多少个子进程,总数翻倍。 - 遇到条件分支,要分别追踪父子返回值。
wait只改变执行顺序/回收子进程,不会创建进程。
输出不确定性:
- 父子进程调度顺序不确定。
- 多个进程
printf的行顺序不确定。 - 如果没有关闭缓冲或没有换行,输出还可能受缓冲影响。
3. exec
语义:
- 用新程序替换当前进程的用户态地址空间。
- pid 不变。
- 成功后不返回到原程序;失败才返回错误。
- 常和
fork配合:子进程exec新程序,父进程wait。
4. wait/waitpid
作用:
- 父进程等待子进程结束。
- 回收子进程退出状态,避免僵尸进程。
- 若没有已结束子进程,调用者进入等待态。
常考表述:
- 内核把调用进程从运行态转为等待态。
- 子进程结束后产生唤醒,父进程回到就绪态。
5. 管道与 I/O 重定向
管道:
- Shell 先创建管道,再 fork 出命令进程。
- 前一个命令的标准输出重定向到管道写端。
- 后一个命令的标准输入重定向到管道读端。
- 匿名管道常用于有亲缘关系的进程。
- 有名管道可通过文件系统路径让无亲缘关系进程通信。
常见 IPC:
- 管道
- 消息队列
- 共享内存
- 信号
- 套接字
I/O 重定向:
- 本质是修改文件描述符表,让 fd 0/1/2 指向文件或管道。
dup/dup2常用于把某个文件描述符复制到标准输入或标准输出。>是标准输出重定向到文件。<是标准输入从文件读取。cmd1 | cmd2中cmd1的 stdout 到管道,cmd2的 stdin 从管道。
五、文件系统结构
1. inode 与目录项
inode 保存:
- 文件类型、权限、属主、时间戳、大小。
- 链接计数。
- 数据块地址索引:直接索引、一级间接、二级间接、三级间接。
目录文件保存:
- 目录项:文件名 + inode 号。
- 目录本身也是文件,内容是目录项。
普通文件与目录文件区别:
- 普通文件内容是用户数据。
- 目录文件内容是目录项,描述该目录下有哪些名字以及对应 inode。
2. 文件最大尺寸
若:
- 物理块大小为
B字节。 - 每个索引项大小为
e字节。 - 直接索引项数为
d。 - 每个索引块可存索引项数
n = B/e。
则最大文件大小:
(d + n + n^2 + n^3) * B
例:
- inode 有 10 个直接索引,1KB 块,4B 索引项,
n=256。 - 最大大小 =
(10 + 256 + 256^2 + 256^3) * 1KB。
2022 变体:
- 12 个直接索引,1KB 块,4B 索引项。
- 最大大小 =
(12 + 256 + 256^2 + 256^3) * 1KB。 - inode 中文件物理结构信息占
15 * 4 = 60B,因为 12 个直接 + 1 个一级 + 1 个二级 + 1 个三级,共 15 个索引项。
3. 目录大小与磁盘空间
目录文件大小:
目录项数量 * 每个目录项大小
占用磁盘空间:
- 至少按物理块取整。
- 若目录数据块数超过直接索引范围,还要额外占用间接索引块。
例:
- 每个目录项 16B,目录下 610 个文件 + 40 个子目录,共 650 项。
- 目录大小
650 * 16 = 10400B。 - 物理块 1KB,则目录数据需要 11 个物理块。
- 若直接索引只有 10 个,还需要 1 个一级间接索引块,所以共占 12 个物理块。
4. open 内核过程
标准答法:
- 用户态调用
open,陷入内核。 - 根据路径逐级查目录,找到目标文件目录项和 inode 号。
- 若 inode 已在活动 inode 表中,增加引用;否则从磁盘读入 inode,建立活动 inode 表项。
- 检查权限和打开方式。
- 建立系统打开文件表项,记录读写方式、当前文件偏移量、指向活动 inode 的指针、引用计数等。
- 在当前进程用户打开文件表中找空项,指向系统打开文件表项。
- 返回该用户打开文件表下标,即文件描述符 fd。
5. read/write 内核过程
read(fd, buf, n):
- 通过 fd 查当前进程用户打开文件表。
- 找到系统打开文件表项,获得当前偏移量和活动 inode。
- 检查打开方式是否允许读。
- 根据 inode 索引把逻辑块号转换为物理块号。
- 从磁盘或缓存读入数据到内核缓冲,再复制到用户缓冲区。
- 更新文件偏移量。
- 返回实际读入字节数。
write(fd, buf, n):
- 同样通过 fd 找系统打开文件表和 inode。
- 检查是否以写方式打开。
- 根据偏移量定位或分配数据块。
- 把用户数据写入缓存/磁盘。
- 更新偏移量、文件大小、inode 修改时间等。
- 若打开方式不允许写,返回错误码。
易错点:
fork后父子进程复制用户打开文件表,但指向同一个系统打开文件表项,所以共享偏移量。- 分别
open同一文件会产生不同系统打开文件表项,偏移量独立。 dup复制的是文件描述符,使两个 fd 指向同一个系统打开文件表项,偏移量共享,引用计数增加。
6. 硬链接与软链接
硬链接:
- 新目录项指向同一个 inode。
- inode 链接计数加一。
- 不新增目标文件 inode。
- 通常不能跨文件系统,通常不链接目录。
- 访问快,实现简单。
软链接/符号链接:
- 新建一个特殊文件,内容是目标路径。
- 有自己的 inode。
- 可跨文件系统,可链接目录。
- 访问时需要解析路径,开销较大;目标删除后可能悬空。
六、历年试卷考点总结
2016-2017
题型概况:
- Q1 UNIX 代码:
open("data.txt", O_RDONLY)、两次fork、read(fd, buffer, 2)、getpid、printf、waitpid。考进程树、输出结果、open系统调用过程。 - Q2 调度理论:所有作业同时到达,FCFS 平均周转时间/平均带权周转时间公式;证明 SJF 平均周转时间最短;SJF 导致长作业饥饿。
- Q3 死锁:给资源总量、已分配、申请、最大需求;用死锁检测判断是否死锁;讨论银行家算法实际困难。
- Q4 请求分页:32 位、1GB 物理内存、2KB 页面、4B 页表项;一级页表项数、二级页表地址划分、反置页表项数;给地址序列和 3 个页框,用 LRU 求页号序列、页框变化和物理地址。
- Q5 文件系统:目录树、目录项大小、目录文件块结构;按链接结构/顺序结构读取文件第 15 块的最少/最多启动磁盘次数。
- Q6 磁盘:位图管理空闲块、磁盘容量、C-SCAN 调度、寻道时间/旋转延迟/传输时间。
- 编程题:按进程间优先关系图,用信号量 P/V 写并发程序。
注意点:
fork后共享打开文件表偏移,所以四个进程依次读到ab、cd、ef、gh,但输出行顺序由调度决定。- SJF 最优证明要写“相邻交换”或“短作业在前使加权累加项最小”,不能只写结论。
- 死锁检测和银行家算法要区分:检测当前是否已死锁;银行家避免未来进入不安全状态。
2017-2018
题型概况:
- Q1 Shell 管道:
cat file1 file2 | sort,考输出、两个子进程关系、管道特点、IPC。 - Q2 调度:两道批处理系统;作业调度按优先数,进程调度 RR;求进入主存时间、结束时间、平均周转和平均带权周转;比较批处理和分时系统。
- Q3 银行家算法:判断安全序列;判断 P1 请求能否满足;若满足后再给一组请求,用死锁检测找死锁进程。
- Q4 请求分页:32 位、1GB、4KB 页面、4B 页表项;一级/二级页表;访问逻辑地址 12300;NRU/LFU/Aging 选牺牲页;颠簸和最佳页面大小。
- Q5 UNIX 文件系统:inode 直接/间接索引,
open过程磁盘读取次数,父子进程读文件物理块数,文件占用空间和最大文件大小,link硬链接过程。 - Q6 磁盘:容量、读写速率、平均旋转等待、位示图大小、FCFS/SSTF/电梯调度。
- 编程题:管程实现读者写者问题。
注意点:
- 二级页表计算必须写出页内偏移 12 位、页表页索引 10 位、页目录 10 位。
- 12300/4096 = 3,所以访问 3 号页;题中驻留 1、2、4、5,因此缺页。
- 最佳页面大小公式:
f(p)=se/p+p/2,这里最优为 8KB,所以 4KB 不合理。
2018-2019
题型概况:
- Q1 UNIX 代码:API 与系统调用区别;
fork实现;进程树;getpid/getppid/sleep/printf输出。 - Q2 作业调度与内存:Buddy 伙伴系统、FCFS 作业调度、RR 平分 CPU,列进入主存/结束时间和关键内存状态。
- Q3 死锁:进程-资源分配图检测;线程使用锁是否可能死锁,OS 能否检测应用内部锁死锁。
- Q4 请求分页:分页缺点、多级页表/TLB;反置页表;给逻辑地址序列和 3 页框,用 LRU 求页框变化和后续物理地址;LRU 实现困难、NRU/Aging 近似;OPT 意义。
- Q5 文件系统:根目录最多文件数、inode 区最多文件数、目录文件占块数、硬链接/软链接、
open内核过程。 - Q6 磁盘:CHS 请求、电梯调度、同柱面扇区优化、读请求和写请求区别。
- 编程题:用管程实现匿名管道,容量 K 的环形队列,
read/write阻塞条件。
注意点:
- 反置页表项数按物理页框算:2GB/4KB =
2^19。 - LRU 精确实现通常不可行,理由是维护精确最近访问顺序代价大。
- 目录文件数据块超过直接索引数时,要额外算间接索引块。
2019-2020
题型概况:
- Q1 中断与 RR 调度开销:时钟中断频率、中断处理、调度、分派 CPU 的时间比例。
- Q2 SPOOLing:比较采用/不采用 SPOOLing 的总运行时间。
- Q3 银行家算法:状态是否安全;P2 请求能否分配;证明满足某个最大需求条件时不会死锁。
- Q4 可变分区:首次适应、最佳适应能否装入作业序列,画内存队列。
- Q5 文件系统一致性:空闲块/分配块不一致、丢失盘块、重复分配等。
- Q6 磁盘 I/O:SSTF、SCAN、C-SCAN 移动臂总量;用信号量或管程实现 SCAN 调度。
- 编程题:猴子过峡谷问题,用信号量避免相反方向同时通过产生死锁。
注意点:
- RR 调度开销题不要漏掉引起调度的多个时钟中断处理时间。
- SPOOLing 的关键是预输入、缓输出和 CPU 处理可重叠。
- 文件系统一致性题要区分“空闲表重复”“分配表重复”“既空闲又分配”“既不空闲也不分配”。
2020-2021
题型概况:
- Q1 Shell:
cat fileA.txt fileB.txt | sort > sorted.txt,考输出文件、进程数、管道、IPC、输入/输出重定向。 - Q2 调度:作业调度 SJF,进程调度抢占式优先级;求进入主存/结束时间和平均周转;列常见调度算法;讨论 I/O 密集型和 CPU 密集型平衡;抢占/非抢占优缺点。
- Q3 银行家算法:安全性、P1 请求、P4 请求。
- Q4 请求分页:32 位、1GB、4KB 页面;二级页表划分;页表项字段;W 位从 1 到 0 的原因;访问地址 2000 缺页;LFU/Aging 选牺牲页;Aging 如何接近 LRU。
- Q5 文件系统:inode 最大文件大小、目录文件大小和磁盘占用、用户打开文件表/系统打开文件表/活动 inode 引用关系、
read过程和物理块数。 - Q6 磁盘调度:FCFS、电梯、SCAN、SSTF。
- 编程题:Hoare/Mesa 风格管程语义转换,用信号量模拟。
注意点:
- 地址 2000 在 4KB 页面下属于 0 号页,不是 2 号页。
- 选择牺牲页时,若计数相同,优先淘汰干净页,避免写回脏页。
- 管道和重定向题要指出:
catstdout 到管道,sortstdin 从管道,sortstdout 到sorted.txt。
2021-2022
题型概况:
- Q1 UNIX 代码:产生 3 个进程,进程树,输出
Count: 20多行;fork/sleep/printf;sleep使进程等待。 - Q2 多道程序设计:可变分区、低地址优先、FCFS 作业调度、RR、设备静态分配;平均周转时间;列作业/进程调度算法;死锁四条件和静态分配破坏占有并等待。
- Q3 银行家与死锁:安全序列;P3 请求能否满足;修改分配和可用资源后检测死锁进程。
- Q4 请求分页:32 位、1GB、1KB 页面、4B 页表项;页表项理论最大数、页框号最大值、页表项信息;从页面大小合理性推断进程平均大小;R 位清零;NRU 替换;TLB 和缺页开销。
- Q5 文件系统:inode 区最多文件数、目录文件不同 inode 号/大小/占用空间;
write因只读打开失败;read涉及间接索引块,共读几个物理块。 - Q6 磁盘调度:FCFS/SSTF/电梯顺序和移动量,SSTF 饥饿。
- 编程题:读者写者问题变体,同时读进程编号总数不大于 N,用 PV 操作实现。
注意点:
- 普通变量在
fork后独立,所以每个进程自己的count不互相影响。 - 静态设备分配不是破坏互斥,而是一次性申请资源,破坏占有并等待。
- 最近未使用 NRU 题要结合 R 位和 W 位,优先淘汰未引用且干净的页。
2022-2023
题型概况:
- Q1 UNIX 代码:8 个进程、进程树、多种输出可能;
setbuf/printf与 I/O;fork/wait/getpid/getppid与进程控制/同步;直接系统调用的弊端。 - Q2 可变分区:最优适应与最坏适应;作业创建/结束时间;内存用户区变化;内碎片和外碎片。
- Q3 自旋锁:单核关中断为何可实现临界区互斥;多核为何失效;基于 XCHG 实现
lock/unlock。 - Q4 死锁检测:给 Allocation、Request、Available,判断当前死锁进程;讨论死锁避免需要何时决策和掌握最大需求。
- Q5 请求分页:32 位、2GB、1KB 页面;页表理论最大尺寸;二级页表划分;多级页表优缺点;反置页表项数;R=0/W=1 原因;CALL 指令访问栈和目标页,FIFO/Clock/NRU 缺页次数;锁定位减少多次缺页。
- Q6 文件系统:inode 中物理结构信息大小;最大文件尺寸;fd 值含义和能否为 0;
dup用途与引用计数;缓存下逻辑块到物理块转换和实际读块数;程序输出。 - Q7 磁盘:FCFS/SSTF/电梯/SCAN 顺序和移动柱面数;同柱面请求归并和扇区循环排序。
- 编程题:管程实现最多 K 个读者的读者写者问题。
注意点:
- fd 一般从 0、1、2 之后开始分配,所以普通
open常返回 3;如果先关闭 0,再exec,新程序里open可能返回 0。 dup后多个 fd 指向同一系统打开文件表项,引用计数增加,共享偏移。- 2022 分页题的二级划分是
14 + 8 + 10,不是常见的10 + 10 + 12。
七、高频易错点清单
调度
- 优先数大小方向必须看题干。
- RR 平分 CPU 时,要动态统计同一时间在内存中的作业数。
- 平均周转时间用到达时间,不是进入主存时间,除非题目明确要求“作业驻留后”的指标。
- SJF 最短平均周转时间成立的前提是运行时间已知,且同一批作业可重新排序。
- 抢占式优先级中,新高优先级作业到达会打断当前进程。
分页
- 地址页号 =
floor(逻辑地址 / 页面大小),页内偏移 =逻辑地址 mod 页面大小。 - 页表项大小影响二级页表划分,不影响页内偏移。
- 反置页表按物理页框数算,不按虚拟页数算。
- R 位会被 OS 周期性清零;W 位表示脏页,不会因为 R 清零而清零。
- Aging 寄存器是数值比较,值越小越久未访问。
- 脏页淘汰前要写回,所以同等条件下优先淘汰干净页。
死锁
Need = Max - Allocation,不要把 Request 当 Need。- 银行家算法的“请求可满足”必须试分配后仍安全。
- 不安全不等于死锁。
- 死锁检测最后未完成的进程才是死锁进程。
- 静态分配破坏占有并等待,不是破坏互斥。
UNIX 进程/系统调用
fork后普通变量各自独立,文件偏移可能共享。printf是 API,不是系统调用;底层可能触发write。exec成功不返回,pid 不变。wait/sleep会使调用进程进入等待态。- Shell 管道命令通常创建两个命令子进程,Shell 是它们的父进程。
- 输出顺序不确定时,应说明由调度顺序决定。
文件系统
- 文件最大尺寸要把直接、一级、二级、三级全部算上。
- 目录文件大小按目录项数算,占磁盘空间按物理块向上取整。
- 数据块超过直接索引范围时,读数据可能还要读间接索引块。
- 硬链接不新增目标文件 inode,只新增目录项并增加链接计数。
- 软链接新增 inode,文件内容是路径。
dup和fork都可能增加系统打开文件表项引用计数,但一般不新增活动 inode。
八、例题
例题 1:SJF 与 FCFS
题目:三个作业同时到达,运行时间分别为 J1=8, J2=4, J3=2。分别用 FCFS 和 SJF 求平均周转时间。
解:
- FCFS 顺序
J1,J2,J3:完成时间分别为 8、12、14,平均周转时间(8+12+14)/3 = 34/3。 - SJF 顺序
J3,J2,J1:完成时间分别为 2、6、14,平均周转时间(2+6+14)/3 = 22/3。
注意:
- 同时到达时,完成时间就是周转时间。
- 若题目还要带权周转时间,要再除以各自运行时间。
例题 2:二级页表划分
题目:32 位逻辑地址,页面大小 1KB,页表项 4B,求二级页表地址划分。
解:
- 1KB =
2^10,页内偏移 10 位。 - 虚页号位数 =
32 - 10 = 22位。 - 一个页表页能放
1KB/4B = 256 = 2^8个页表项,所以页表页索引 8 位。 - 页目录位数 =
22 - 8 = 14位。 - 划分:
14 位页目录 + 8 位页表页索引 + 10 位页内偏移。
注意:
- 不要把 1KB 页面套成 4KB 的
10+10+12。
例题 3:Aging 页面置换
题目:某时刻 4 个驻留页的 Aging 寄存器为:页 1=1100,页 2=0111,页 3=1001,页 4=0111。页 2 是脏页,页 4 是干净页。发生缺页时淘汰谁?
解:
- Aging 值越小越久未访问。
- 页 2 和页 4 都是
0111,同为最小。 - 页 2 是脏页,淘汰需写回;页 4 干净。
- 因此优先淘汰页 4。
注意:
- 页面置换不只看算法主指标,参考答案常要求“结合 W 位考虑”。
例题 4:银行家算法请求能否满足
题目:某进程 P1 当前 Need=(1,2,0),系统 Available=(1,1,1)。若 P1 请求 (1,1,0),是否一定能分配?
解:
- 先看请求是否超过 Need:
(1,1,0) <= (1,2,0),通过。 - 再看请求是否超过 Available:
(1,1,0) <= (1,1,1),通过。 - 但不能直接说可以。必须试分配后运行安全性算法。
- 若试分配后仍存在安全序列,才可以;否则拒绝。
注意:
- 很多题的坑就在“资源够”但“分配后不安全”。
例题 5:fork 与打开文件表
题目:父进程 fd=open("data.txt") 后执行两次 fork(),然后每个进程执行 read(fd, buf, 2)。文件内容为 abcdefghijkl。如果读操作依次由 pid 2、3、4、5 执行,各自读到什么?
解:
open在fork前执行,所有子进程复制 fd,但 fd 指向同一个系统打开文件表项。- 该系统打开文件表项的文件偏移量共享。
- 第一个进程读
ab,偏移变 2。 - 第二个读
cd,偏移变 4。 - 第三个读
ef,偏移变 6。 - 第四个读
gh,偏移变 8。
注意:
- 读到的内容由实际调度顺序决定,不一定按 pid 顺序。
- 如果每个进程分别
open文件,则偏移量独立,结果不同。
例题 6:inode 最大文件大小
题目:inode 有 10 个直接索引项,一级/二级/三级间接索引各 1 个;物理块 512B;索引项 4B。求单个文件理论最大大小。
解:
- 每个索引块可存
512/4 = 128个索引项。 - 直接索引可寻址
10个数据块。 - 一级间接可寻址
128个数据块。 - 二级间接可寻址
128^2个数据块。 - 三级间接可寻址
128^3个数据块。 - 最大大小 =
(10 + 128 + 128^2 + 128^3) * 512B。
注意:
- 题目若问“占多少磁盘空间”,还可能要把间接索引块本身也算进去;若问“文件最大尺寸”,通常只算可存用户数据的大小。
例题 7:硬链接过程
题目:执行 link /test/demo.dat /demo.dat,文件系统主要做什么?
答题模板:
- 查找
/test/demo.dat,得到目标文件 inode 号。 - 查找新路径
/demo.dat的父目录,即根目录。 - 在父目录中增加目录项:名字
demo.dat+ 目标 inode 号。 - 将目标 inode 的链接计数
i_nlink加一。 - 不复制文件数据,不新增目标文件 inode。
注意:
- 硬链接是多个目录项指向同一个 inode。
九、考前速记
- 32 位 + 4KB + 4B PTE:二级页表
10/10/12。 - 32 位 + 1KB + 4B PTE:二级页表
14/8/10。 - 32 位 + 2KB + 4B PTE:二级页表
12/9/11。 - 反置页表项数 = 物理内存 / 页面大小。
Need = Max - Allocation。- 银行家:先检查 Request,再试分配,再安全性检测。
fork:变量独立,打开文件表偏移可能共享。exec:成功不返回,pid 不变。dup:复制 fd,指向同一系统打开文件表项。- 硬链接:同 inode,链接计数加一。
- 软链接:新 inode,内容是路径。
- SJF:平均周转时间优,但长作业可能饥饿。
- RR:时间片太小开销大,太大退化 FCFS。
- Aging:右移寄存器,R 放最高位,值越小越先淘汰。
- NRU:优先
(R=0,M=0),再(0,1),再(1,0),最后(1,1)。