操作系统 · 第 2 章

第 2 章 进程管理

进程与线程;三态转换图;同步与互斥、PV 操作(含生产者-消费者填空模板);死锁四条件;调度算法与周转时间计算。

2.1 进程与线程

"程序是静态的菜谱,进程是动态的做菜过程。"

  • 进程——程序在某个数据集上的一次动态执行过程,是系统进行资源分配的基本单位。
  • 程序——静态的指令集合,存成文件放在磁盘上;一个程序可以对应多个进程(打开两个记事本就是两个进程)。
  • 进程由程序段、数据段、PCB(进程控制块)三部分组成;PCB 是进程存在的唯一标志——这句话是考点。

进程 vs 线程(对比表必背):

进程线程
定位资源分配的基本单位CPU 调度的基本单位
资源拥有独立地址空间和资源共享所属进程的资源(同一进程内线程共享内存)
开销创建、切换、通信开销大切换开销小、通信方便(直接读写共享变量)
关系一个进程可包含多个线程线程不能独立于进程存在
进程的特征(了解)
  • 动态性(最基本特征,有生命周期)、并发性、独立性、异步性、结构性。
课堂练习(3 题)
  1. 进程存在的唯一标志是什么? 答:PCB(进程控制块)。
  2. CPU 调度的基本单位是进程还是线程? 答:线程(进程是资源分配的基本单位,线程是调度的基本单位)。
  3. 同一个进程内的多个线程共享什么?各自的私有内容是什么? 答:共享进程的内存空间和资源;各自有独立的栈和寄存器现场(执行上下文)。

2.2 进程状态与转换(必考图)

三态图背下来,转换条件能填出箭头上的字。

进程三态及状态转换图:就绪、运行、阻塞与创建、终止
图 2-1 进程三态转换图(必考):阻塞不能直接到运行,就绪也不能直接到阻塞
三种基本状态的准确定义
  • 就绪——万事俱备,只差 CPU。
  • 运行——正在占用 CPU 执行。
  • 阻塞(等待)——在等某个事件(I/O 完成、信号量),给它 CPU 也没用。
易错(选择题高发)
  • 阻塞 → 运行是错的:阻塞的进程事件完成后只能先回到就绪,再被调度才能运行。
  • 就绪 → 阻塞是错的:阻塞必须由正在运行的进程主动发起(发起 I/O),没上过 CPU 的程序无从阻塞。
课堂练习(3 题)
  1. 进程正在执行 I/O 请求后进入什么状态?I/O 完成后又进入什么状态? 答:运行 → 阻塞;I/O 完成后阻塞 → 就绪(不能直接回运行)。
  2. 时间片用完的进程从运行变成什么状态? 答:就绪。
  3. 下列转换哪个不可能发生:A. 运行→阻塞 B. 阻塞→运行 C. 就绪→运行 D. 运行→就绪 答:B(阻塞不能直接到运行,必须先到就绪再被调度)。

2.3 同步与互斥:PV 操作(核心考点)

软考最爱出的一种题:在程序的①②③处填 P 或 V。学会本节有保底分。

两个概念先分清
  • 互斥——多个进程抢同一个资源(打印机、变量),同一时刻只许一个用。争的是"我能不能进"。
  • 同步——多个进程有先后配合关系(生产完才能消费、先算完 a 再算 b)。争的是"你完没完"。
  • 被争夺的资源叫临界资源,访问它的代码段叫临界区,同一时刻只允许一个进程处于临界区。
P、V 操作的定义(信号量机制)
P(S):S = S − 1 ;若 S < 0,则本进程阻塞(进等待队列)
V(S):S = S + 1 ;若 S ≤ 0,则唤醒一个等待进程

理解:S 代表"可用的资源数"(含负数时其绝对值表示排队等待的进程数)。
申请资源用 P(减),释放资源用 V(加)——先 P 后用,用完 V,成对出现。
两种最基本的用法(模板要能默写)
① 互斥(信号量初值 = 1):
   P(mutex)                      // 进门先申请;第一个进程拿到,后来的堵在门外
     临界区:使用打印机 / 改共享变量
   V(mutex)                      // 出门还钥匙

② 同步(先做 A,后做 B;信号量初值 = 0):
   进程甲:执行 A 动作 → V(S)     // 做完 A 就"发信号"
   进程乙:P(S) → 执行 B 动作     // 等信号到了才开始 B
互斥信号量初值为什么是 1?
  • 初值 = 资源数。打印机只有一台 → S=1:第一个进程 P 后 S=0 顺利进入; 第二个进程 P 后 S=−1 被阻塞排队;第一个进程 V 后 S=0 并唤醒排队的进程。
  • 同步信号量初值 = 0:因为 B 必须等 A 发信号(V)之后才能通过 P。
易错
  • P 是申请(减),V 是释放(加),方向记反必错。
  • 互斥的两个进程里,P/V 必须成对且在同一进程内包住临界区;别只 P 不 V(死锁)或先 V 后 P。
课堂练习(3 题)
  1. 互斥信号量初值应该设多少?同步信号量(先后关系)初值呢? 答:互斥初值 1;同步初值 0(等对方 V 之后才能 P 通过)。
  2. 进程执行 P(S) 后 S 由 0 变为 −1,说明什么? 答:该进程被阻塞,进入等待队列(此时有 1 个进程在等)。
  3. 信号量 S 当前为 −2,执行一次 V(S) 后 S 变成多少?发生什么? 答:V 先加 1,S 变为 −1;因结果 ≤ 0,唤醒一个等待进程(原本有 2 个在排队,唤醒后还剩 1 个)。

2.4 PV 操作经典题型(生产者-消费者)

生产者消费者问题与 PV 操作示意图
图 2-2 生产者-消费者:empty / full 记数量,mutex 保护缓冲区,先 P 资源再 P 互斥

考试就爱考这个模型的填空。把这道题吃透,遇到就稳。

场景:有大小为 N 的缓冲区。生产者进程生产一个产品放入缓冲区,放满 N 个就等一下; 消费者进程每消费一个产品腾出一个位置,缓冲区空就等一下。

初始信号量: mutex = 1   // 互斥访问缓冲区
             empty = N   // 空位数量(初始全部是空的)
             full  = 0   // 已有产品数(初始没有产品)

生产者进程:                          消费者进程:
   循环 {                                 循环 {
     生产一个产品                            P(full)     // 有货吗?没有就等
     P(empty)   // 有位置吗?没有就等           P(mutex)    // 抢缓冲区锁
     P(mutex)   // 抢缓冲区锁                  从缓冲区取一个产品
     把产品放入缓冲区                          V(mutex)    // 还锁
     V(mutex)   // 还锁                       V(empty)    // 空位 +1(通知生产者)
     V(full)    // 产品 +1(通知消费者)        消费掉产品
   }                                       }
解题三步法
  1. 找资源:缓冲区本身(互斥 mutex)、空位 empty、产品 full。
  2. 定初值:互斥 1;空位 = 容量 N;产品 = 0。
  3. 排操作顺序:就资源数量做 P(不够就等),做完动作做 V(通知别人)。 先对资源 P,再对互斥 P(顺序反了可能死锁)。
课堂练习(3 题)
  1. 缓冲区容量 N=10,empty 与 full 的初始值分别是多少? 答:empty=10,full=0。
  2. 如果把生产者的 P(empty) 与 P(mutex) 顺序互换(先 P(mutex) 后 P(empty)),可能出什么问题? 答:可能死锁——生产者占着互斥锁等空位,而腾空位需要消费者拿到互斥锁,互相等待。
  3. 生产者放入产品后 V(full) 的作用是什么? 答:通知等待的消费者"有货了";若消费者在等待则唤醒它。

2.5 死锁:四个必要条件必背

死锁的循环等待示意图
图 2-3 循环等待:P1 占 R1 要 R2、P2 占 R2 要 R1,形成环路

"产生死锁的条件"考的是四件套,缺一不可——答题先写这四条。

死锁的四个必要条件
  • 互斥——资源同一时刻只能被一个进程占用。
  • 请求并保持(占有并等待)——拿着手里的,还想要别的。
  • 不可剥夺(不可抢占)——资源只能由占有者主动释放。
  • 循环等待——存在一条进程—资源的环形等待链(A 等 B 的资源,B 等 A 的)。
对策:预防 / 避免 / 检测解除
  • 预防——破坏四个条件之一(如资源一次性全部分配,破坏"请求并保持";按序申请资源,破坏"循环等待")。
  • 避免——分配前先判断安全性,经典算法是银行家算法(知道名字与用途即可)。
  • 检测与解除——允许发生,定期查死锁,然后剥夺资源/撤销进程来解除。

顺带认识:死锁(互相等,全动不了)、活锁(都在让路,谁也不前进)、饥饿(优先级低的一直排不上队)——概念题能区分即可。

课堂练习(3 题)
  1. 产生死锁的四个必要条件是什么? 答:互斥、请求并保持、不可剥夺、循环等待。
  2. "破坏循环等待"通常用什么办法? 答:给资源统一编号,规定所有进程必须按编号递增顺序申请资源。
  3. 判断:只要破坏了四个必要条件中的一个,死锁就一定不会发生。 答:正确——四条件必须同时成立才可能死锁,破坏其一即可预防。
银行家算法安全性检查
图 2-5 银行家算法完整例题:算 Need → 逐轮推进可用量 → 得出安全序列

2.6 进程调度与周转时间(会算)

进程调度甘特图与周转时间计算
图 2-4 FCFS 与 SJF 的甘特图 + 周转/带权周转时间全套算例

给定作业到达时间与运行时间,算"谁先执行、周转时间多少"。

算法思想特点
先来先服务 FCFS按到达先后排队公平;短作业排在长作业后面会等很久
短作业优先 SJF谁运行时间短谁先上平均周转时间最短;长作业可能饿死
时间片轮转 RR每人一个时间片,轮着来响应快,适合分时;切换开销大
优先级调度优先级高的先上灵活;要防低优先级饥饿(可用老化提高优先级)
两个公式(计算题就靠它)
  • 周转时间 = 完成时间 − 到达时间(在我的手里总共待了多久)。
  • 带权周转时间 = 周转时间 ÷ 运行时间(待的时间是干活的几倍,越接近 1 越好)。
例题:三个作业 FCFS vs SJF

作业 A(到达 0,运行 7)、B(到达 2,运行 4)、C(到达 4,运行 1)。

FCFS(按到达先后:A→B→C):
  A:0−7 完成 → 周转 7       B:7−11 完成 → 周转 11−2=9
  C:11−12 完成 → 周转 12−4=8     平均周转 = (7+9+8)/3 = 8

SJF(谁短谁先;A 先跑,2 时 B 到、4 时 C 到,C 比 B 短):
  A:0−7 → 周转 7     C:7−8 → 周转 8−4=4     B:8−12 → 周转 12−2=10
  平均周转 = (7+4+10)/3 = 7      ← 更短,印证"短作业优先平均周转最短"
课堂练习(2 题)
  1. 某作业运行时间 5,等待后在第 12 时刻完成,到达时刻为 2,它的周转时间和带权周转时间是多少? 答:周转时间 = 12 − 2 = 10;带权周转时间 = 10 ÷ 5 = 2。
  2. 哪种调度算法的平均周转时间最短?(不考虑抢占) 答:短作业优先(SJF)。