操作系统 02|进程到底被谁推着走?

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 ;栈不共享

以上仅为复习优先级排序 ,不作为押题依据。


八、易错点清单

  1. 把"被抢占"当成"阻塞" ------ 抢占只剥夺 CPU,进程仍在就绪态。这是全章第一错。

  2. 把"时间片用完"当成"阻塞" ------ 同上,回就绪。

  3. 混淆"就绪"与"唤醒" ------ 唤醒专指阻塞→就绪;就绪→运行叫调度,不叫唤醒。

  4. 以为阻塞进程能自己醒 ------ 阻塞→就绪只能由别的进程或中断触发。

  5. 以为新进程是执行态 ------ 创建完一般是就绪态,等调度。

  6. 以为终止父进程必然终止子进程 ------ 孤儿进程照样能活。

  7. 以为父子进程共享地址空间 ------ 不共享,各有 PCB、各有地址空间。

  8. 以为同进程线程各有独立地址空间 ------ 它们共享进程地址空间。

  9. 以为 ULT 由 OS 管理 ------ ULT 由线程库管,内核不知道它存在,也不给它建 TCB。

  10. 忘了 ULT 的致命缺点 ------ 一个线程阻塞,整个进程跟着阻塞 ,且用不了多核。

  11. 以为管道能双向、容量受磁盘限制 ------ 半双工、容量受内存限制。

  12. 以为设备分配会创建进程 ------ 不创建,只是修改数据结构。


速查表(文末收藏版)

复制代码
# -------- 一句话判状态 --------
等 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 与多线程模型部分按教材通行口径整理

相关推荐
坐看风云变幻2 小时前
《系统架构师成长之路》第 2 期|计算机基础:从一次 malloc 看懂内存管理
操作系统
2401_872418784 小时前
操作系统|进程管理、线程、系统调用、进程间通信与信号
操作系统·pcb·os
艾iYYY1 天前
【无标题】
linux·开发语言·网络·操作系统
沫璃染墨2 天前
《Qt从零入门系列(十四):QThread多线程详解——从线程创建到客户端阻塞处理》
开发语言·c++·笔记·qt·ui·交互·线程
打不了嗝 ᥬ᭄2 天前
计算机系统基础:异常、中断与 I/O 的完整脉络
操作系统·计算机系统基础·linux系统调用·异常与中断·io与dma
我不会起名字3223 天前
Pod 一直 Pending:调度器 5 类失败原因与 kubectl describe 的正确读法
云原生·kubernetes·调度·排查
doujiaozh3 天前
我在 Win7 老电脑上从零手搓了一个操作系统内核:32位分页、中断接管与 Shell 终端
操作系统·汇编语言
CS创新实验室3 天前
一棵树怎么做到“自平衡还不太费力“?——红黑树的旋转与染色
数据结构·算法·红黑树·408·计算机考研
辰丁电子4 天前
allegro入门教程-菜单栏Analyze
fpga开发·pcb设计·pcb工艺·pcb·layout