2018 年第 27 题问:下列选项中,可能导致当前进程 P 阻塞的事件是 ------Ⅰ 申请临界资源、Ⅱ 从磁盘读数据、Ⅲ 系统将 CPU 分配给高优先级的进程。
我当年选了 D(Ⅰ、Ⅱ、Ⅲ 全要),答案是 C(仅 Ⅰ、Ⅱ)。
我当时的理由听起来挺顺:"CPU 被别人抢走了,我当然就卡住了呀,那不就是阻塞吗?"
后来才明白,我把"没有 CPU "和"在等别的东西 "当成了一回事。进程被抢占之后,它什么都没在等,只差 CPU 而已 ------一旦再被选中就能继续跑,所以它去的是就绪态,不是阻塞态。
判断归属的办法其实就一句:进程是在「等 CPU」,还是在「等 CPU 之外的东西」?
-
等 CPU → 就绪态(随时能跑)
-
等 I/O、等资源、等信号 → 阻塞态(给 CPU 也跑不动)
这一句能直接解决状态转换里七八成的题。这篇就从它往下讲:进程是什么 → PCB → 三态模型 → 哪些事件触发哪条线 → 进程和线程到底差在哪。
〇、先花两分钟:进程到底是个什么东西
先给个能贯穿全篇的类比。看一遍就行,不用背。
菜谱和炒菜
| 概念 | 现实类比 | 说明 |
|---|---|---|
| 程序(Program) | 一份菜谱 | 静态的,写在纸上,永远不变 |
| 进程(Process) | 一次炒菜的过程 | 动态的,有开始有结束,中途可能被打断 |
| PCB | 这道菜的进度卡 | 火候到哪了、用了哪些料、下一步该干嘛 |
同一个程序可以跑出多个进程(同一份菜谱同时做三锅),它们是各自独立的。
术语 :PCB (Process Control Block,进程控制块)------操作系统给每个进程建的一份档案,记录了进程的全部信息 。它是进程存在的唯一标志:PCB 在,进程就在;PCB 被销毁,进程就没了。
PCB 里大致装四类东西:进程标识信息(PID)、处理机状态信息(寄存器、PC、PSW,切换时要存好 )、进程调度信息(状态、优先级、等待事件)、进程控制信息(资源清单、父子关系)。
三态模型四条转换线与「两条不存在的转换」、状态转换事件对照、进程 vs 线程对比表、共享与私有资源清单、ULT/KLT 对照
一、进程的诞生和退场
创建新进程:三步走,最后一步最容易答错
408 真题 2010 年第 24 题 :导致创建新进程的操作是(Ⅰ 用户登录成功 Ⅱ 设备分配 Ⅲ 启动程序执行)?答案 C(仅 Ⅰ、Ⅲ)。
Ⅱ 为什么不成立 :设备分配是系统在数据结构里改几个表项("这台打印机归你了"),用不着为它单开一个进程 。 记住四类典型触发:用户登录、作业调度、系统提供服务(用户请求)、应用自己请求 (
fork)。
408 真题 2021 年第 24 题 :创建新进程时必须完成 的是(Ⅰ 申请空白 PCB Ⅱ 初始化 PCB Ⅲ 设置进程状态为执行态)?答案 B(仅 Ⅰ、Ⅱ)。
Ⅲ 是这道题的杀招。新进程诞生时不会被直接设成执行态 ------CPU 正被别人占着,通常是设成就绪态,排队等调度。答题时一不小心就会把 Ⅲ 也勾上。
408 真题 2020 年第 29 题 (父进程与子进程,选错误 的):答案 B(父进程与子进程共享虚拟地址空间)。
子进程创建时会拿到一套自己的资源与地址空间 (Linux 上
fork之后是写时复制),父子各有一份 PCB,不是共享地址空间。A 并发执行 ✓、C 各有 PCB ✓、D 不能同时用同一临界资源 ✓。
终止进程:什么一定做,什么不一定做
408 真题 2024 年第 24 题 :操作系统在终止进程时不一定执行 的是?答案 A(终止子进程)。
子进程的生命周期并不总是跟着父进程走 ------父进程先走一步,子进程照样能继续跑(这就是孤儿进程 ,它会被
init/systemd领养)。而 B 回收内存、C 撤销 PCB、D 回收设备这三件是终止进程时必做的收尾工作。
二、三态模型:四条线,两条不存在
必须能自己画出来的那个图,就是它。
被调度选中(获得 CPU)
┌───────────────────────────────┐
↓ │
┌──────────┐ ┌──────────┐
│ 就绪态 │ ─────── ① 调度 ─────→ │ 运行态 │
│ Ready │ │ Running │
└──────────┘ └────┬─────┘
↑ │
│ │ ② 时间片用完
│ │ 或被高优先级进程抢占
│ ④ I/O 完成 / 资源可用 / │
│ V 操作唤醒(被动) │ ③ 请求 I/O / 申请临界资源
│ │ / P(wait) 操作失败(主动)
│ ↓
│ ┌──────────┐
└───────────────────────────│ 阻塞态 │
│ Blocked │
└──────────┘
必背口诀(年年考)
运行 → 阻塞,是进程「主动」的 (它自己去申请 I/O、申请资源,没拿到才停下来的)。 阻塞 → 就绪,是「被动」的 (由别的进程或中断把它唤醒,阻塞的进程没法自己叫醒自己 )。 阻塞 → 运行、就绪 → 阻塞 ------ 这两条线不存在。
为什么这两条不存在?
-
阻塞 → 运行:阻塞解除后要先在就绪队列里排队,CPU 不能凭空发下来。
-
就绪 → 阻塞 :就绪态是"万事俱备只欠 CPU",它还没上 CPU 跑,就不可能主动去申请资源。这是最容易被忽略的一条。
事件对照表(和图互相印证)
| 当前状态 | 触发事件 | 目标状态 | 主/被动 |
|---|---|---|---|
| 就绪 | 被调度程序选中 | 运行 | --- |
| 运行 | 时间片用完 | 就绪 | 被动失去 CPU |
| 运行 | 被更高优先级进程抢占 | 就绪 | 被动失去 CPU |
| 运行 | 请求 I/O / 申请临界资源 / P(wait) 失败 | 阻塞 | 主动 |
| 阻塞 | I/O 完成 / 资源可用 / V(signal) 唤醒 | 就绪 | 被动 |
| 运行 | 进程结束(终止原语) | 终止 | --- |
三、真题逐个事件核对:就绪还是阻塞?
这一节把开头那条判断规则放进真题里验证。
「抢占」和「时间片用完」→ 都是就绪
408 真题 2015 年第 25 题 (执行态→就绪态):答案 D(被高优先级进程抢占)。
A 执行
P(wait)、B 申请内存失败、C 启动 I/O 设备 ------ 这三个都在等资源 ,统统进阻塞。只有 D 是"CPU 被拿走了,但我没在等别的东西",进就绪。这就是开头那道题的同型复述。
408 真题 2023 年第 27 题 (换成线程的问法):可能导致该线程由执行态变为就绪态 的是?答案 C(主动出让 CPU)。
A 键盘输入、B 缺页异常、D 执行
wait()------ 后两者都会等待 某件事完成,属于阻塞。只有主动让出 CPU 是"我还能跑,但先给别人",回就绪队列。 顺带:这道题虽以线程命题,状态转换的结论对线程成立。
「等资源」→ 才是阻塞
408 真题 2018 年第 27 题 (开头那道):答案 C(仅 Ⅰ、Ⅱ) ------ Ⅲ「系统将 CPU 分配给高优先级的进程」使进程进入就绪。
408 真题 2022 年第 28 题 (执行→阻塞,四条判断):答案 D(仅 Ⅰ、Ⅲ、Ⅳ)。
| 序号 | 事件 | 归属 | 理由 |
|---|---|---|---|
| Ⅰ | 进程 P 读文件 | 阻塞 ✓ | 等磁盘 I/O |
| Ⅱ | 进程 P 的时间片用完 | 就绪 ✗ | 只是被收回 CPU |
| Ⅲ | 进程 P 申请外设 | 阻塞 ✓ | 外设被占,等分配 |
| Ⅳ | 执行信号量 wait() |
阻塞 ✓ | 信号量 ≤0,等 signal() |
「唤醒」只对已经阻塞的进程有效
408 真题 2019 年第 24 题 (可能将进程唤醒 的事件):答案 C(仅 Ⅰ、Ⅱ)。
Ⅰ I/O 结束 → 唤醒等这个 I/O 的进程 ✓;Ⅱ 某进程退出临界区 → 唤醒被挡在门外的进程 ✓;Ⅲ 当前进程时间片用完 → 它自己进就绪队列排队 ,不是唤醒任何人 ✗。
⚠️ 一个很容易糊的词:「唤醒」专指"阻塞 → 就绪"这一个动作。就绪≠唤醒,调度≠唤醒(调度是就绪→运行)。看到这三个词先想清楚对的是哪条线。
I/O 完成后必做什么
408 真题 2014 年第 26 题 :进程的读磁盘操作完成后,OS 针对该进程必做 的是?答案 A(修改进程状态为就绪态)。
这是"阻塞 → 就绪"这条线的标准问法。降优先级、加时间片、分配用户内存都不一定发生 ,但"把它从阻塞挪到就绪"是一定的。
什么时候会触发调度
408 真题 2021 年第 27 题 :可能引起进程调度程序执行 的是(Ⅰ 中断处理结束 Ⅱ 进程阻塞 Ⅲ 进程执行结束 Ⅳ 时间片用完)?答案 D(Ⅰ、Ⅱ、Ⅲ、Ⅳ 全要)。
只要当前进程不再占用 CPU ,就得有人决定下一个是谁 ------ ①中断处理结束时要检查是否该换人 ②阻塞要腾 CPU ③结束要腾 CPU ④时间片到要让位。四条都算。 反过来说:什么时候不能调度? 处理中断的过程中、进程在操作系统内核临界区内、原子操作期间------这些场合调度会出乱子。
四、进程 vs 线程:一张表,一句话
必背的那句(2012 年原题):进程是资源分配的基本单位,线程是 CPU 调度的基本单位。
| 对比项 | 进程(Process) | 线程(Thread) |
|---|---|---|
| 定义 | 程序的一次执行过程 | 进程内的一个执行流 |
| 地位 | 资源分配的基本单位 | CPU 调度的基本单位 |
| 地址空间 | 独立的地址空间 | 共享所属进程的地址空间 |
| 切换开销 | 大(要换地址空间、刷 TLB) | 小(同进程内不换地址空间) |
| 通信 | 需要 IPC 机制 | 直接读写共享变量 |
| 健壮性 | 一个崩溃不影响别人 | 一个崩了拖垮整个进程 |
408 真题 2012 年第 31 题 (选正确的):答案 A(不管系统是否支持线程,进程都是资源分配的基本单位)。
B 把两个单位说反了;C 错在用户级线程的切换不需要内核支持 (这正是它快的根源);D 错在同进程的线程是共享地址空间,而不是各有各的。
共享什么、私有什么(2011 与 2024 两道题同一张清单)
| 共享(进程级) | 私有(线程级) |
|---|---|
| 代码段、数据段(全局变量 )、堆 | 栈(含栈指针) |
| 打开的文件与文件描述符 fd | 程序计数器 PC、寄存器组 |
| 信号处理函数、当前工作目录 | 线程局部存储 |
408 真题 2011 年第 25 题 :进程 P 创建的若干线程不能共享 的是?答案 D(某线程的栈指针)。
408 真题 2024 年第 28 题 :Ta、Tb 可共享的是(Ⅰ 进程地址空间 Ⅱ 线程 T 的栈 Ⅲ fd)?答案 B(仅 Ⅰ、Ⅲ)。
两道题隔了 13 年,考的同一件事:每个线程必须有自己的栈 (各自的函数调用链不一样),所以栈和栈指针永远不共享 ;而
fd和地址空间永远是共享的。
五、用户级线程与内核级线程
| 对比项 | 用户级线程 ULT | 内核级线程 KLT |
|---|---|---|
| 管理者 | 线程库(用户空间) | 操作系统内核 |
| 内核是否知道它存在 | 不知道,内核只看到进程 | 知道,内核直接调度它 |
| 切换开销 | 小(用户态完成,不进内核) | 大(要进内核) |
| 一个线程阻塞 | 整个进程都被阻塞 ⚠️ | 只阻塞它自己,同进程其他线程照跑 |
| 能否利用多核 | 不能 | 能 |
| 是否需 OS 支持 | 不需要,不支持线程的 OS 上也能跑 | 需要 |
408 真题 2019 年第 23 题 (选错误 的):答案 B(操作系统为每个用户级线程建立一个线程控制块)。
用户级线程在内核眼里不存在 ,内核当然不会给它建 TCB------它的管理全在用户空间的线程库里。这也正好解释了 ULT 那个致命缺点:某线程调了阻塞式系统调用,内核以为整个进程都在等,于是别的线程一起陪葬。
三种多线程模型 (多对一、一对一、多对多)记住一句话就够:只有「多对多」才算真正兼顾了并发度和开销 ;一对一(n个 ULT 对n个 KLT)并发好但开销大;多对一则并发不了多核。
六、IPC 一角:管道(2014 真题)
进程间通信(IPC)主要有四大类:共享存储、消息传递、管道通信、信号。其中管道每年都可能出现。
408 真题 2014 年第 31 题 (关于管道通信,选正确的):答案 C(进程对管道进行读操作和写操作都可能被阻塞)。
逐条判:
-
A 错 :一个管道是半双工 的,同一时刻只能单向流动。要双向通信就得建两个管道。
-
B 错 :管道是内存中的一块固定大小缓冲区 (通常是内存中的一页),受内存限制,不受磁盘容量限制。
-
C 对 :管道满时写进程阻塞,管道空时读进程阻塞 ------ 两边都可能被卡。
-
D 错 :一个管道允许多个进程读或写,只要互斥访问即可。
七、真题都考在哪
按公开考频统计(2009--2025),「进程与线程」相关内容(含状态转换、PCB、ULT/KLT、IPC)在操作系统里属于高频区 ,约 16 次小题 + 1 次综合题 ,几乎每年必有一道,且状态转换类题目占其中的一半以上。
| 年份·题号 | 一句话考点 |
|---|---|
| 2010(24) | 什么导致创建进程 → 用户登录、启动程序;设备分配不算 |
| 2011(25) | 线程不能共享 → 栈指针 |
| 2012(31) | 进程/线程的基本单位 → 进程管资源、线程管调度 |
| 2014(26) | I/O 完成后必做 → 改为就绪态 |
| 2014(31) | 管道 → 半双工、容量受内存限制、读写都可能阻塞 |
| 2015(25) | 执行→就绪 → 被高优先级抢占 |
| 2018(27) | 什么导致阻塞 → 申请临界资源、读盘;被抢占不算 |
| 2019(23) | ULT/KLT → OS 不为 ULT 建 TCB |
| 2019(24) | 什么能唤醒 → I/O 结束、退出临界区;时间片用完不算 |
| 2020(29) | 父/子进程 → 不共享虚拟地址空间 |
| 2021(24) | 创建进程必做 → 申请+初始化 PCB,是就绪态不是执行态 |
| 2021(27) | 什么引起调度 → 四条都要 |
| 2022(28) | 执行→阻塞 → 读文件、申请外设、wait();时间片用完不算 |
| 2023(27) | 线程执行→就绪 → 主动出让 CPU |
| 2024(24) | 终止进程不一定做 → 终止子进程 |
| 2024(28) | 线程共享 → 地址空间与 fd ;栈不共享 |
以上仅为复习优先级排序 ,不作为押题依据。
八、易错点清单
-
把"被抢占"当成"阻塞" ------ 抢占只剥夺 CPU,进程仍在就绪态。这是全章第一错。
-
把"时间片用完"当成"阻塞" ------ 同上,回就绪。
-
混淆"就绪"与"唤醒" ------ 唤醒专指阻塞→就绪;就绪→运行叫调度,不叫唤醒。
-
以为阻塞进程能自己醒 ------ 阻塞→就绪只能由别的进程或中断触发。
-
以为新进程是执行态 ------ 创建完一般是就绪态,等调度。
-
以为终止父进程必然终止子进程 ------ 孤儿进程照样能活。
-
以为父子进程共享地址空间 ------ 不共享,各有 PCB、各有地址空间。
-
以为同进程线程各有独立地址空间 ------ 它们共享进程地址空间。
-
以为 ULT 由 OS 管理 ------ ULT 由线程库管,内核不知道它存在,也不给它建 TCB。
-
忘了 ULT 的致命缺点 ------ 一个线程阻塞,整个进程跟着阻塞 ,且用不了多核。
-
以为管道能双向、容量受磁盘限制 ------ 半双工、容量受内存限制。
-
以为设备分配会创建进程 ------ 不创建,只是修改数据结构。
速查表(文末收藏版)
# -------- 一句话判状态 --------
等 CPU -> 就绪态
等 CPU 之外的东西 -> 阻塞态
主动: 运行→阻塞(自己去申请没拿到)
被动: 阻塞→就绪(别人唤醒)
不存在的两条线: 阻塞→运行 / 就绪→阻塞
# -------- 事件归属(高频)--------
抢占/时间片用完/主动出让CPU -> 就绪
请求I-O/申请临界资源或外设/wait()失败/缺页 -> 阻塞
I/O完成/资源可用/V(signal)唤醒 -> 阻塞→就绪
# -------- PCB 与进程生命周期 --------
PCB = 进程存在的唯一标志
创建: 申请空白PCB → 初始化PCB → 置就绪态(不是执行态!) 2021(24)
导致创建: 用户登录/作业调度/系统提供服务/应用请求; 设备分配不算 2010(24)
终止时必做: 回收内存 + 撤销PCB + 回收设备
终止时不一定: 终止子进程(孤儿进程) 2024(24)
父子: 可并发/各有PCB/不共享虚拟地址空间 2020(29)
# -------- 进程 vs 线程 --------
进程 = 资源分配的基本单位 线程 = CPU调度的基本单位 2012(31)
进程: 独立地址空间/切换开销大/需IPC/互不影响
线程: 共享地址空间/切换开销小/直接读写共享变量/一个崩了拖垮全进程
共享: 代码段/全局变量/堆/打开的文件fd/信号处理 2011(25).2024(28)
私有: 栈(含栈指针)/PC/寄存器组/线程局部存储
# -------- ULT vs KLT --------
ULT: 线程库管理/内核不知道/切换快/一个阻塞全进程阻塞/不能多核/不需OS支持
KLT: 内核管理/内核知道/开销大/只阻塞自己/能多核
OS 不为 ULT 建 TCB (2019-23 B 错)
多线程模型: 一对一(并发好开销大) / 多对一 / 多对多(折中最优)
# -------- 管道 --------
半双工, 双向要两个管道 / 容量受内存限制(一页), 不是磁盘
管道满写阻塞, 管道空读阻塞 -> 读写都可能阻塞 (2014-31 C)
允许多个进程读写, 只需互斥
一句话总结 :状态转换的题全都可以压缩成一个问题------这个进程到底在等什么。等 CPU 就是就绪,等别的任何东西就是阻塞;再记住"运行→阻塞是主动、阻塞→就绪是被动、剩下的两条线不存在",这一章的图就不需要死背了。
本文依据
-
知识点:操作系统第 2 章「进程与线程」(进程概念与 PCB、进程状态与转换、线程概念与实现方式、进程间通信)
-
考频:公开考频统计(2009--2025)整理,「进程与线程」相关考点约 16 次小题 + 1 次综合题 ,状态转换类占其中一半以上。统计仅用于排优先级,不作为押题依据
-
引用真题:408 真题 2010(24)、2011(25)、2012(31)、2014(26)、2014(31)、2015(25)、2018(27)、2019(23)、2019(24)、2020(29)、2021(24)、2021(27)、2022(28)、2023(27)、2024(24)、2024(28)(题干要点、选项与答案据公开真题库逐条核对)
-
注:2019(23)、2023(27)、2024(28) 的解析要点引自笔记录入版本;文中 ULT/KLT 与多线程模型部分按教材通行口径整理
三态模型四条转换线与「两条不存在的转换」、状态转换事件对照、进程 vs 线程对比表、共享与私有资源清单、ULT/KLT 对照