进程调度与状态转换
进程调度决定就绪进程中谁获得 CPU,状态转换说明进程为什么能运行、为什么要等待。系统调用和中断又会改变 CPU 的执行模式。综合题往往把这几件事写在同一段经历里,需要分别追踪。
这个板块包含哪些知识
进程与同步图谱中的执行主体和资源等待,是本页的起点。向调度和运行环境展开后,主要有四组知识:
- 进程与线程:PCB、执行现场、资源共享和上下文切换。
- 进程状态:新建、就绪、运行、阻塞、终止,以及各条转换的触发事件。
- 调度:算法、抢占条件、时间片、动态优先级、公平性和周转等指标。
- CPU 运行模式:用户态与内核态、系统调用、异常和外部中断。
最需要分清的是三个层次:发生了事件,不一定切换进程;进入内核态,也不一定使当前进程阻塞。例如时钟中断可能只更新计时;读设备时,数据已就绪与需要等待的后果也不同。
常见考点与题型
综合题可能组合下面几类小问。先看要求求什么,再确定需要调用哪些知识。
| 题型 | 题干中的线索 | 解题思路 |
|---|---|---|
| 调度过程模拟 | 到达、运行时间、优先级、时间片 | 列事件时间线并维护就绪队列、剩余时间;换人前检查调度条件 |
| 周转、等待和响应指标 | 首次运行、完成时刻、平均指标 | 从模拟结果取时刻后计算;含 I/O 时单独扣除阻塞时间 |
| 动态优先级与饥饿 | 运行惩罚、等待补偿、优先数公式 | 先确定数值大小方向,再检查每项怎样影响获得 CPU 的机会 |
| 系统调用与状态转换 | 陷入、I/O、中断、唤醒、返回 | 沿事件逐步标注目标进程状态与 CPU 模式,分别作答 |
| 参数或机制比较 | 时间片、中断周期、进程或线程切换 | 说明参数影响的具体环节,再结合工作负载判断开销与响应变化 |
解题前要弄清的关系
一、题目未引入挂起态时,采用五状态模型,边是固定的
新建 → 就绪 ⇄ 运行 → 终止
↑ ↓
└── 阻塞
常见状态转换的触发条件是:运行 → 就绪是被抢占或时间片用完,运行 → 阻塞是自己等资源或等 I/O,阻塞 → 就绪是等的事情发生了。「阻塞 → 运行」和「就绪 → 阻塞」两条边不存在——阻塞的进程醒来只能先回就绪队列。见 进程的状态、状态转化。
二、调度算法按「比什么、能不能抢」两列记
| 算法 | 比什么 | 抢占 | 见 |
|---|---|---|---|
| 先来先服务 | 到达时刻 | 否 | 先来先服务 |
| 短作业优先 | 要求运行时间 | 有抢占式变体 | 最短作业优先 |
| 高响应比优先 | (等待 + 运行) ÷ 运行 | 否 | 最高响应比优先 |
| 优先级 | 优先级值(题目会交代大小方向) | 两种都有 | 优先级调度 |
| 时间片轮转 | 只按队列排队 | 时间片到就换 | 时间片轮转 |
| 多级反馈队列 | 队列层号 + 各层时间片 | 是 | 多级反馈队列 |
常用指标包括:周转时间 = 完成 − 到达、带权周转 = 周转 ÷ 运行、等待时间 = 周转 − CPU 运行 − I/O 等阻塞时间(无阻塞的简化题才可省去最后一项),见 调度指标。
三、抢占只发生在几个固定时刻
时钟中断、更高优先级进程进入就绪队列、当前进程阻塞或结束。题目说「仅在时钟中断时抢占」,就要把所有换人动作对齐到中断时刻,见 调度时机、调度方式、上下文切换。
四、进内核只有三条路
系统调用(自愿陷入)、外部中断、内部异常。特权指令(开关中断、置 PSW、直接访问 I/O)用户态一律不能执行,见 CPU 运行模式、系统调用、异常。
五、一次「读键盘」的系统调用是一条固定链
用户进程发起系统调用 → 陷入内核 → 设备未就绪:置阻塞态、插入阻塞队列
→ 切换到其他进程 → 用户敲键 → 键盘中断 → 驱动程序把字符搬进系统缓冲区
→ 唤醒该进程、插入就绪队列 → 被调度后从系统调用返回
各类题的解法
前两条只在给了到达时刻和运行时间的调度题上用,后三条按问法挑一条用。
先把题干抄成一条时刻线
可以用甘特图表示 CPU 占用区间,再用“时刻 → 事件 → 调度结果”补充抢占原因和状态变化。2026#45 的参考答案就是这种写法,八行写完全程:
10 P1、P2 到达,CPU 空闲 → 调度 P2(首次)
20 时钟中断,P4 优先级更高 → 抢占,调度 P4(首次)
70 时钟中断,P4 时间片用完,优先级 −1 → 调度 P2
80 时钟中断,P2 完成 → 调度 P4
90 时钟中断,P4 完成 → 调度 P1(首次)
140 时钟中断,P1 时间片用完,优先级 −1 → 调度 P3(首次)
180 时钟中断,P3 完成 → 调度 P1
225 P1 完成,全部结束
每一行只写三样东西:时刻、事件、换给谁。“时间片用完”和“被更高优先级进程抢占”要分开标注——这一年前者优先级减 1,后者不变,标错一行后面全错。
次数分开数,不要一起数
- 时钟中断次数按间隔从头数到尾:10、20、…、220,共 22 次;
- 本题 CPU 调度次数按参考解答的统计范围记为 7 次;其他题先确认是否计入首次分派、调度后仍运行原进程等情况;
- 首次调度时刻回到时刻线上找每个进程第一次被标「首次」的那一行。
这三项的统计对象不同,应分别从事件记录中核对。
优先数公式题按「静态 + 惩罚 − 补偿」写
priority = nice + k1 × cpuTime − k2 × waitTime (k1 > 0, k2 > 0)
写完必须补一句每一项的作用,因为分是按项给的。2016#46 的【评分说明】写明:公式含 nice 给 1 分、用 cpuTime 增大优先数给 1 分、用 waitTime 减小优先数给 1 分;只要三个量都用上,其他合理公式同样给分。
饥饿的理由也是固定一句:静态优先数下,只要就绪队列里总有优先级更高的进程,另一个就一直得不到 CPU。注意先看题目说的是「优先数小者优先」还是「优先级大者优先」,2016#46 是前者。
排序与状态题,一问一句
2023#46 的四问是这类题的完整样本,答法各自固定:
| 问法 | 固定答法 |
|---|---|
| 某操作的前一个 / 后一个是谁 | 套第五条那条链,逐步对号 |
| 之后 CPU 一定切换到别的进程 | 「插入阻塞队列」之后 |
| 之后调度程序才可能选中它 | 「插入就绪队列」之后 |
| 某操作的代码属于哪一层 | 与具体设备寄存器打交道的那一步归设备驱动程序 |
| 中断处理程序执行时,进程和 CPU 各是什么态 | 进程阻塞态、CPU内核态,两个态分别回答 |
问「进程处于什么状态」时答的是发起系统调用的那个进程,不是正在运行的那个;问「CPU 处于什么态」时答的是特权级,两者不要混成一句。
参数变化题只答方向和理由
在该题工作负载与规则下,时间片变大可减少因时间片耗尽引起的调度;时钟中断间隔变小会增加中断处理开销,但并不保证每次中断都引起进程切换(2026#45 第 2 问)。作答应说明方向和因果;若题目改变了抢占或优先级规则,或要求确切次数,需要重新模拟。
调度指标:从完成的时间线取数
响应时间是首次获得 CPU 的时刻减到达时刻,周转时间是完成时刻减到达时刻;等待时间只计在就绪队列中的累计时间。比如到达 0、首次运行 2、完成 12,累计运行 6、阻塞 3,则响应为 2,周转为 12,等待为 12−6−3=3。
做模拟时同步记录剩余运行时间、剩余时间片和就绪队列。多个事件同一时刻发生时,按题设规定处理;若题目没有规定且会影响结果,应说明采用的次序,而不是默默选择一种。
历年题索引
三道题各是一种问法,下面这张表用来查「这一年的口径」。
| 真题 | 主线 | 这一年特别问了什么 |
|---|---|---|
| 2016#46 | 动态优先数设计 | 静态优先数为何饥饿;waitTime 起什么作用 |
| 2023#46 | 系统调用全过程排序 | 哪一步之后必然切换;哪一步属于键盘驱动程序 |
| 2026#45 | 优先级 + 时间片轮转 | 中断与调度各几次;四个进程的首次调度时刻 |
另有四处小问挂在这一支上:2025#46 问 PCB 在内核区、scanf 时进程处于阻塞态;2017#45 问 scanf 期间的状态变化;2018#45 问进程切换与同进程内线程切换时页目录基址寄存器是否变化;2021#45 问用户程序能否执行开关中断。