☰
操作系统复习笔记:从进程调度到死锁,一条主线串起核心考点
2026/10/14 6:53:10 网站建设 项目流程

简介:操作系统期末复习笔记,面向高校计算机相关专业学生,用于期末系统梳理教材重点与高频考点。内容涵盖操作系统目标、发展历程、四大基本特性、主要功能,以及第二章进程管理的核心框架:前趋图、进程状态转换、PCB、内核与处理机状态;同时用较大篇幅整理进程同步与信号量机制,包括整型、记录型、AND型、信号量集,以及利用信号量实现互斥、同步、前驱关系,适合对照教材查漏补缺。资源包为1个docx格式笔记文档,约1.17MB,可直接编辑打印,便于按章节复习或制作思维导图。已有777人学习下载,适用于考前集中冲刺的在校大学生。笔记语言精炼,条理清晰,将抽象概念转化为易记要点,配合进程同步等难点展开,能帮助读者快速构建知识体系。

1. 操作系统复习笔记:先抓住主线,别让一门课变成四门课

操作系统期末复习,最常见的翻车姿势不是题刷得少,而是复习到一半发现自己把进程、内存、文件系统和死锁当成了四门课在背。上课能听懂,例题也能跟着算出来,但合上书一问“临界资源和临界区到底啥关系”,脑子里就开始打架。这篇笔记想解决的就是这件事:把进程调度、同步互斥、内存管理、磁盘调度串成一条主线,再给每个模块配一套能直接上考场的手算套路。不管你是平时听课质量一般、想考前一个月兜底,还是已经学完一轮想冲高分,这份复习笔记都按“先立框架、再练算法题、最后背易错结论”来组织。所有内容都能用纸笔复现,不依赖任何在线题库或平台资料。

2. 进程与线程:把状态转换图和三个调度算法串成一条主线

2.1 进程状态转换图:手绘三遍,比背十遍笔记管用

进程管理的核心考点高度集中:状态转换、调度算法、线程与进程的对比。其中状态转换是每次必考的基础题,而且特别喜欢放在选择题里考场景判断,比如“某个进程在等待打印机,它处于什么状态”。所以第一件事不是背概念,而是把五状态转换图练成肌肉记忆。

五状态包括:创建、就绪、运行、阻塞、终止。记忆口诀很简单:就绪等 CPU,运行做事情,阻塞等 I/O。三个主要转换必须闭眼能画:就绪→运行由调度器完成;运行→就绪有两个触发条件,时间片耗尽或更高优先级任务抢占;运行→阻塞不是进程主动让出 CPU,而是它自己在等待某事件,比如发起一次磁盘读请求。最容易错的搭配是“运行→阻塞”和“阻塞→就绪”成对出现,中间必须回到就绪状态,不能直接从阻塞回运行。

我一般复习时会用三遍法画图:第一遍照着笔记抄,第二遍合上笔记从零画,第三遍只写五个状态名,然后脑补三条主线的转换条件和触发源。第三遍能顺畅画出来,说明这一块真题怎么出都拦不住你。顺带一提,挂起状态在很多教材里会扩展成七状态图,但期末看考纲重点,五状态足够应付绝大多数填空选择。

2.2 调度算法手算模板:周转时间、等待时间、带权周转时间

调度这一节,论述题可以少看,但计算题一定要练到手算不出错。核心公式就三个。周转时间 = 完成时间 − 到达时间;等待时间 = 周转时间 − 服务时间(也可以直接算进程从就绪到开始运行之间的累计等待);带权周转时间 = 周转时间 ÷ 服务时间。注意带权周转时间没有单位,它是一个比值,衡量“这个进程为了完成服务多等了多久”。

下面用一个最干净的例子把 FCFS、SJF、RR 三个算法一次串起来。假设三个进程同时到达,服务时间 A=8、B=4、C=2。

先来先服务 FCFS 按 A、B、C 顺序执行,完成时间分别是 8、12、14,周转时间分别是 8、12、14,平均周转时间 11.33,带权周转时间分别是 8/8=1、12/4=3、14/2=7。短作业优先 SJF 非抢占式会先执行 C,再 B,最后 A,完成时间分别是 2、6、14,周转时间分别是 2、6、14,平均周转时间 7.33,带权分别是 1、1.5、1.75。时间片轮转 RR 取时间片 q=4,执行顺序是 A(0-4)、B(4-8)、C(8-10)、A(10-14),完成时间分别是 14、8、10,周转时间分别是 14、8、10,平均周转时间 10.67。

算法A 周转B 周转C 周转平均周转平均带权周转
FCFS8121411.333.67
SJF(非抢占)14627.331.42
RR(q=4)1481010.672.92

从这组数字能看出三个结论:SJF 在“所有进程同时到达”时平均周转时间最短,这是它被称为最优的原因;RR 的周转时间介于两者之间,但响应时间最好;FCFS 最直观但可能让短任务排长队,形成护航效应。考场上一旦让你比较调度算法,优先摆平均周转和平均带权周转两张表,比写一百字论述有用。

2.3 线程与进程的对比:一张表记三个“是否”

线程和进程的区别属于高频概念题,但问法很固定,无非是“哪个是资源分配单位、哪个是调度单位、切换谁更轻”。真正容易丢分的是把“共享地址空间”和“共享全局变量”混在一起答。

进程是资源分配的基本单位,它拥有独立的地址空间、打开的文件、PCB 等资源;线程是 CPU 调度的基本单位,同一个进程里的线程共享进程的地址空间和资源。所以线程切换只切换线程上下文,不切换地址空间,开销远小于进程切换。这里有一个常见误区:线程不拥有资源,但它可以使用所属进程的资源,比如某个线程出错导致进程崩溃,所有线程一起完蛋,这是“线程共享”带来的副作用。

一句话记忆方式:进程是“资源包”,线程是“执行流”。复试或期末简答题如果让你列举线程的优势,就写三点:创建和切换开销小、线程间通信不需要内核干预、可以充分利用多核并行。至于进程间通信,把管道、消息队列、共享内存、信号量这四种常见方式各自一句话写上,概念就补全了。

3. 同步、互斥与死锁:PV操作和银行家算法的手算流程

3.1 生产者—消费者模型:三个信号量的初始值与 P/V 顺序

并发同步这一节,最稳的复习方式不是背代码,而是背信号量的“角色表”。以有限缓冲区生产者—消费者模型为例,设置了三个信号量。mutex 保护缓冲区这个临界资源,初值为 1;empty 记录空缓冲单元数,初值为 N;full 记录已占用缓冲单元数,初值为 0。考试最爱挖的坑是让考生填初始化值,N 代表缓冲区大小,不是缓冲区的编号。

#define N 64 semaphore mutex = 1; // 互斥信号量,保护缓冲区的读写 semaphore empty = N; // 空缓冲单元数量,初始时全部为空 semaphore full = 0; // 已填充缓冲单元数量,初始为 0 int in = 0, out = 0; // 环形缓冲区读写指针 void producer() { while (1) { item = produce_item(); P(empty); // 先申请一个空位,没有空位则阻塞 P(mutex); // 再申请缓冲区互斥访问权 buffer[in] = item; in = (in + 1) % N; V(mutex); // 释放缓冲区锁 V(full); // 通知消费者有新的数据 } } void consumer() { while (1) { P(full); // 先确认缓冲区有数据 P(mutex); // 再申请访问缓冲区 item = buffer[out]; out = (out + 1) % N; V(mutex); V(empty); // 释放一个空位 consume_item(item); } }

这段代码有几处细节值得说。P(empty) 和 P(full) 属于资源信号量,P(mutex) 属于互斥信号量,顺序必须是“先资源后互斥”。如果生产者先 P(mutex) 再 P(empty),当缓冲区满时生产者拿着 mutex 卡在 P(empty) 上,消费者想执行 P(mutex) 也进不来,双双陷入死锁。另一个细节是 in 和 out 指针必须放在锁内更新,如果把它放在 V(mutex) 之后,理论上会出现读数写数位置不一致的问题。同样,互斥锁的 V 操作一定要和 P 操作配对出现在同一个临界区边界,漏一个 V(mutex) 就会让系统永久卡死。

3.2 读者—写者问题:count 计数为什么要一把独立锁

读者—写者问题在期末考试里地位很高,因为它比生产者—消费者模型多了一个“读读允许并发”的机制。核心思想是:读者之间不互斥,写者和其他任何人都互斥。实现方案是用一个读者计数 count 记录当前读者数量,并用 rw 信号量控制写者访问。

semaphore rw = 1; // 读者与写者共享的互斥信号量,写者独占 semaphore mutex = 1; // 保护读者计数 count 的锁 int count = 0; // 当前正在读的读者数量 void reader() { while (1) { P(mutex); count++; if (count == 1) P(rw); // 第一个读者进入时抢占写者锁 V(mutex); read_data(); P(mutex); count--; if (count == 0) V(rw); // 最后一个读者离开时释放写者锁 V(mutex); } } void writer() { while (1) { P(rw); write_data(); V(rw); } }

这段代码的关键在 count 为什么要单独加锁。如果没有 mutex 保护,两个读者同时执行 count++,最终结果可能只加了一次,这就是典型的共享变量竞争条件。同时要注意,不是每个读者都执行 P(rw),只有第一个读者才跟写者竞争锁,最后一个读者才释放锁,这样多个读者就能同时读数据。

这种实现是读者优先的,写者可能被源源不断的读者饿死。如果题目要求写者优先,常见做法是再加一个 w 信号量形成一个“二级互斥”,让新读者先等在 w 上。期末能把这个变体看懂即可,手写出完整代码属于加分项而非必考题。

3.3 银行家算法:安全序列如何一步步推出来

银行家算法是操作系统中少有的、能把“安全性”这个概念变成一道纯粹手算题目考的点。考场上的解题步骤非常固定,背熟五步就能拿分。

第一步,检查请求是否合法:Request[i] 不能超过 Need[i]。第二步,检查系统是否有钱可借:Request[i] 不能超过 Available。第三步,试分配:Available 减去 Request,Allocation 加上 Request,Need 减去 Request。第四步,调用安全性检查算法:用 Work 复制 Available,把所有进程的 Finish 都置为 False,反复扫描,找到一个 Finish 为 False 且 Need 每项都不大于 Work 的进程,执行 Work += Allocation 并标记 Finish=True。第五步,若所有进程都能 Finish,说明系统处于安全状态,批准本次请求;否则不批准并回滚试分配。

用一道非常经典的例题把过程走一遍。系统有 5 个进程 P0 到 P4,3 类资源 A、B、C,当前 Available=(3,3,2),各进程的 Allocation 和 Need 如下表。

进程AllocationNeedAvailable
P0(0,1,0)(7,4,3)(3,3,2)
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)

手工推安全序列时用 Work 表示当前可用资源,它是动态变化的。初始 Work=(3,3,2),先找 Need 满足条件的进程可以看到 P1 的 Need(1,2,2) 不大于 Work,于是把 P1 的资源加进 Work,Work 变成 (5,3,2),P1 标记完成。之后 P3 的 Need(0,1,1) 可满足,Work 变 (7,4,3);P4 的 Need(4,3,1) 可满足,Work 变 (7,4,5);P0 的 Need(7,4,3) 可满足,Work 变 (7,5,5);最后 P2 的 Need(6,0,0) 可满足,Work 变 (10,5,7)。安全序列为 P1→P3→P4→P0→P2。

再进一步,如果此时 P1 发出请求 Request=(1,0,2),按五步走:Request 没有超过 Need,也没有超过 Available,试分配后状态变为 Available=(2,3,0),P1 的 Allocation 变为 (3,0,2),Need 变为 (0,2,0)。再用安全性检查扫描,仍然能按类似顺序找到一个安全序列,所以这次请求应当批准。考试时把每一步资源变化写在草稿纸上,别跳步,这类题基本不会失分。顺带背一下死锁四必要条件:互斥、持有并等待、不可剥夺、循环等待,前三个是资源本身属性,第四个是前三个的结果,破坏任意一个就能预防死锁。

4. 内存与文件系统:地址换算和两个“排队”算法的统一套路

4.1 逻辑地址到物理地址:三步换算和一张页表

内存管理这章,最常考的计算题是分页存储管理的地址转换。解题模式完全固定:页号 = 逻辑地址 ÷ 页大小,页内偏移 = 逻辑地址 % 页大小,物理地址 = 页帧号 × 页大小 + 页内偏移。整个过程就是除法、取余、查表、乘法加法四步。

设页面大小为 1KB,逻辑地址为 2500,页表内容是页 0 对应帧 2、页 1 对应帧 4、页 2 对应帧 6。2500 除以 1024 得到页号 2,余数 452,查页表得到帧号 6,物理地址 = 6 × 1024 + 452 = 6596。这里必须检查页号是否越界,如果算出来的页号大于页表长度,直接判定为越界中断,而不是继续算下去。

步骤操作本例结果
1逻辑地址 ÷ 页大小页号 = 2
2逻辑地址 % 页大小页内偏移 = 452
3查页表帧号 = 6
4帧号 × 页大小 + 偏移物理地址 = 6596

段页式存储的地址结构是段号 + 页号 + 页内偏移,多一层查表,但原理不变。复习时重点区分两个概念:页表是“逻辑页 → 物理帧”的映射表,页表项保存在内存中,因此一次数据访问要访问两次内存,第一次查页表,第二次取数据,这也是为什么会有快表 TLB 来加速访问。论述题如果问“为什么要引入快表”,答案核心就是这句话。

4.2 页面置换算法: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 最优置换在理论上淘汰“未来最长时间不会被访问”的页面,手算时把整个访问序列往后看,找每个页面下一次出现的位置,距离最远的那个就是淘汰对象。FIFO 只看页面进入内存的先后顺序,先进来先淘汰,不看访问频率。LRU 看的是过去,淘汰“最近最久没有被访问”的页面,需要维护一个访问顺序列表。三个算法的结果差异很大。

置换算法缺页次数缺页率
OPT945%
LRU1260%
FIFO1575%

这个结果就是一份现成的论证材料:OPT 是最理想情况的基准,实际不可实现,因为它需要预知未来;LRU 性能接近 OPT,但实现开销高;FIFO 实现最简单,却可能出现 Belady 异常——页框数增加时缺页次数反而增多。Belady 异常只出现在 FIFO 上,这是一个高频填空题。Clock 算法也叫二次机会算法,每个页框有一个使用位,替换时从指针位置开始扫描,遇到使用位为 0 的页面就淘汰,遇到使用位为 1 的页面先改成 0 并继续扫描,相当于给最近被访问过的页面第二次机会。

手算 LRU 时有个小习惯可以避免出错:不要把页面在内存中待了多少时间当成判断依据,而是维护一个“最近访问序列”,每次访问命中就把该页面移到序列末尾,缺页时淘汰序列头部。这样即使访问序列很长,也不会算乱。OPT 手算前先把整个序列抄在小白纸上,每个位置标注出对应页面下一次出现的坐标,后续就可以快速找“最远的未来”,速度会快很多。

4.3 磁盘调度:SSTF、SCAN、C-SCAN 的寻道顺序与长度

磁盘调度是文件系统里少有的计算题,考法和页面置换高度相似:给你一个磁道请求队列和当前磁头位置,让你按各种算法算出寻道顺序和总寻道长度。本质上也是一个“排队”问题,只是排队依据从页面引用变成了磁道距离。

假设当前磁头在 100 磁道,移动方向由内向外(磁道号增大方向),请求队列为 55、58、39、18、90、160、150、38、184。先算最短寻道时间优先 SSTF:磁头从 100 出发,离得最近的是 90(距离 10),然后 58、55、39、38、18,再掉头处理 150、160、184。SSTF 的寻道顺序是 100→90→58→55→39→38→18→150→160→184,总寻道长度 248。

SCAN 电梯算法要求磁头先沿一个方向走到头再回头处理反向请求。按照先向大磁道号方向移动的规则,顺序是 100→150→160→184,到边界后回头处理 90→58→55→39→38→18。总寻道长度是 50+10+24+94+32+3+16+1+20=250。C-SCAN 循环扫描则不同,磁头只在一个方向服务,到达边界后直接返回起点,返回途中不处理请求,因此顺序是 100→150→160→184,然后回到 18,再沿着增大的方向处理 38→39→55→58→90,总寻道长度比 SCAN 更长一些。

算法寻道顺序总寻道长度
FCFS55,58,39,18,90,160,150,38,184498
SSTF90,58,55,39,38,18,150,160,184248
SCAN150,160,184,90,58,55,39,38,18250
C-SCAN150,160,184,18,38,39,55,58,90322

考试最容易扣分的地方是“方向”漏写。SCAN 和 C-SCAN 的规则都依赖初始方向,题目没有说明时默认按当前移动方向继续。答完寻道顺序后,建议顺手把“假设方向为先向大磁道号移动”这句话写在草稿里,既能让阅卷人看懂,也能提醒自己别在后续计算里方向前后不一致。

5. 操作系统复习避坑:考前最容易翻车的四个理解误区

5.1 带权周转时间算不对:分母用了完成时间

现象:调度计算题公式背得滚瓜烂熟,算到带权周转时间却总是跟标准答案差一截。

原因:很多人把带权周转时间理解成“周转时间 ÷ 完成时间”,而正确公式是“周转时间 ÷ 服务时间”。服务时间是进程需要占用 CPU 的总时长,完成时间是进程真正结束的时刻,两者概念完全不同。在一个多程序并发场景里,进程的完成时间包含了排队等待,用它做分母会得到一个更小但毫无意义的比值。

解决:手算时固定写三行:一行完成时间,一行周转时间(=完成时间−到达时间),一行带权周转时间(=周转时间÷服务时间)。养成先列完成时间再依次向下算的习惯,能有效避免公式串位。

5.2 PV 代码写得顺、信号量初值填错:empty/full 身份混淆

现象:生产者—消费者模型的代码逻辑能默写,结果填空题让填信号量初值,把 full 填成 N、empty 填成 0。

原因:没搞清楚两个资源信号量的语义。empty 表示空位置数量,初始当然是 N;full 表示已填充的数据单元数量,初始当然是 0。这两个初值在生产者和消费者眼里视角相反,但数量总和永远等于 N。把 full 和 empty 填反,相当于告诉消费者缓冲区里已经有 N 个数据,消费者会疯狂去读空缓冲,逻辑彻底崩掉。

解决:在信号量定义旁边写一句话注释:“empty 是生产者眼里的空位,full 是消费者眼里的存货”。每次复习都默写这三个初值,配合代码一起过,比单独背单词有效。

5.3 LRU 和 OPT 被当成同一种淘汰:一个是看过去,一个是看未来

现象:手算 OPT 时,直接按 LRU 的“最近最久未使用”规则淘汰,算出来的缺页次数和标准答案差几个。

原因:两种算法名字相近,口诀都有“最久”两个字,但方向完全相反。LRU 看历史访问记录,淘汰的是过去最久没用的页面;OPT 看未来的访问序列,淘汰的是未来最远才被用到或未来根本不用的页面。考试环境下,很多考生一紧张就把 OPT 当成“从当前帧里挑一个最老的”。

解决:OPT 手算前把整个访问序列往后多看五到六个位置,确定每个候选页面下一次访问的距离;LRU 手算时维护一个“最近访问顺序”列表,每次命中后更新页面位置。如果序列末尾存在某些页面以后再也不出现,OPT 优先淘汰它们,LRU 则没有这种预知能力。

5.4 索引节点和目录项分不清:目录是字典,inode 是身份证

现象:文件管理选择题问“删除文件时先删除什么”,有人答“删除 inode”,被扣分。

原因:目录项存放的是文件名与 inode 编号的对应关系,它相当于文件系统的字典;inode 存放的是文件属性、权限、大小和数据块索引地址,相当于文件的身份证。删除文件时,系统先把目录项从目录中移除,并且把 inode 的链接计数减一,只有链接计数归零时 inode 才会被真正回收。硬链接就是这么来的:多个目录项指向同一个 inode,删除一个目录项不会让数据消失。

解决:记一句话“目录是文件系统的字典,inode 是文件的身份证;字典记录身份证号,身份证记录文件在哪存”。理解了这个映射关系,硬链接和软链接的区别也能顺下来。

6. 考前一晚的默写验证法:用一张白纸还原整张知识地图

复习笔记看到最后,最有效率的验证手段不是再翻一遍书,而是拿一张 A4 白纸,把整门课的知识地图从头默写一遍。我的做法是把关键词压缩成一张清单,不写完整解释,只写提示词,然后合上笔记逐项展开。

模块必须能默写的点
进程调度五状态转换图,周转/等待/带权周转三个公式,FCFS、SJF、RR 选择逻辑
并发与死锁生产者三个信号量初值,P 操作顺序,银行家算法五步
内存管理页号/偏移/帧号换算公式,OPT、FIFO、LRU 的淘汰规则
文件与磁盘SSTF、SCAN、C-SCAN 寻道规则,inode 与目录项区别

默写的时候不用按顺序死磕,先写自己最有把握的模块,卡住的地方就是真正的薄弱点。我当年复习操作系统时,第一遍感觉全是重点,合上笔记开始默写,才发现居然连“阻塞到就绪的转换条件”都要想好几秒。那晚我就只补了这一处,第二天考到相关选择题时一眼就锁定了答案,没有多浪费一分钟。如果你时间也紧,试试这个方法:放下笔记,白纸铺开,能写多少写多少,写不出来的就是考前最后要攻的地方。它比任何笔记都诚实,希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询