【操作系统入门】第四章:进程调度算法——操作系统的大脑如何决策
本系列共10篇,这是第4/10篇。在第三章,我们理解了进程与线程的基本概念。今天,我们将深入操作系统最核心的决策机制——调度算法,探索CPU时间这个宝贵资源是如何被分配的。
开篇:调度——操作系统的终极决策难题
想象一下,你是机场的塔台调度员。眼前有数十架飞机等待起飞:有的载着数百名乘客,有的是紧急医疗航班,有的只是小型私人飞机。你只有一条跑道。你该让哪架飞机先飞?
这就是操作系统调度器面临的困境。CPU就像那条唯一的跑道,而进程/线程就是等待起飞的飞机。调度算法的选择,直接决定了整个系统的"用户体验"——是流畅响应还是卡顿不堪。
第一部分:调度基础——概念与指标
1.1 调度器的层次结构
现代操作系统的调度通常分为三个层次:
- 长期调度(作业调度):决定哪些程序从磁盘被加载到内存中,变为就绪进程。控制系统的多道程序度。
- 中期调度:在内存紧张时,将某些进程暂时换出到磁盘(挂起),待条件允许时再换入。我们在内存管理章节会详述。
- 短期调度(CPU调度):这是我们本章的重点——决定就绪队列中哪个进程/线程下一个获得CPU使用权。
1.2 调度决策的发生时机
调度可能在以下时刻被触发:
- 进程从运行态转换为阻塞态(如I/O请求)
- 进程退出终止
- 进程从运行态转换为就绪态(如时间片用完、被更高优先级进程抢占)
- 进程从阻塞态转换为就绪态(如I/O完成)
- 时钟中断发生,检查是否需要调度
1.3 评估调度算法的关键指标
要评判一个调度算法的好坏,我们需要量化指标:
- CPU利用率:CPU忙碌时间的百分比。理想情况下接近100%。
- 吞吐量:单位时间内完成的进程数量。
- 周转时间:从进程提交到进程完成的总时间(
完成时间 - 到达时间)。 - 等待时间:进程在就绪队列中等待的总时间。
- 响应时间:从提交请求到第一次产生响应的时间(对交互式系统至关重要)。
调度算法的根本目标就是优化这些指标的组合。
第二部分:经典调度算法详解
让我们通过一个具体的例子来分析各种算法:假设有4个进程P1、P2、P3、P4,它们的到达时间和CPU执行时长(突发时间)如下:
| 进程 | 到达时间 | 突发时间 |
|---|---|---|
| P1 | 0 | 8 |
| P2 | 1 | 4 |
| P3 | 2 | 9 |
| P4 | 3 | 5 |
2.1 先来先服务(FCFS)
- 思想:最简单的调度算法,按照进程到达就绪队列的顺序分配CPU。
- 特点:非抢占式——一旦进程获得CPU,就会一直运行直到完成或阻塞。
- 调度顺序:P1(0-8) → P2(8-12) → P3(12-21) → P4(21-26)
- 计算指标:
- 平均等待时间 = [(0-0) + (8-1) + (12-2) + (21-3)] / 4 = (0+7+10+18)/4 = 8.75
- 平均周转时间 = [(8-0) + (12-1) + (21-2) + (26-3)] / 4 = (8+11+19+23)/4 = 15.25
- 优点:实现简单,公平。
- 缺点:护航效应——短进程可能排在长进程后面长时间等待,导致平均等待时间较长。
2.2 最短作业优先(SJF)
- 思想:选择下一个CPU突发时间最短的进程。理论上可以证明SJF能产生最小平均等待时间。
- 特点:可以是抢占式(最短剩余时间优先,SRTF)或非抢占式。
- 非抢占SJF调度:
- 在时间0,只有P1到达,执行P1(0-8)
- 在时间8,P2、P3、P4都已到达,选择突发时间最短的P2(8-12)
- 接着选择P4(12-17),最后P3(17-26)
- 计算指标:
- 平均等待时间 = [(0-0) + (8-1) + (17-2) + (12-3)] / 4 = (0+7+15+9)/4 = 7.75
- 平均周转时间 = [(8-0) + (12-1) + (26-2) + (17-3)] / 4 = (8+11+24+14)/4 = 14.25
- 优点:理论上的最优平均等待时间。
- 缺点:
- 可能产生饥饿:长进程可能永远得不到调度。
- 无法预知未来:实际中无法准确知道进程的下一个CPU突发时间。
2.3 优先级调度
- 思想:为每个进程分配一个优先级,选择优先级最高的进程。优先级可以是内部定义(基于内存需求、时间限制等)或外部定义(用户级别)。
- 特点:可以是抢占式或非抢占式。
- 问题:可能导致低优先级进程饥饿。
- 解决方案:老化——随着进程等待时间的增加,逐步提高其优先级。
2.4 轮转调度(RR)
- 思想:专为分时系统设计。为每个进程分配一个固定的时间片,进程在时间片用完后被抢占,并放回就绪队列末尾。
- 特点:抢占式,特别适合交互式系统。
- 假设时间片 = 4:
- 时间0-4:P1执行(剩余4)
- 时间4-7:P2执行(到达1,执行3个单位完成)
- 时间7-11:P3执行(剩余5)
- 时间11-15:P4执行(剩余1)
- 时间15-19:P1执行(剩余0,完成)
- 时间19-23:P3执行(剩余1)
- 时间23-24:P4执行(剩余0,完成)
- 时间24-26:P3执行(剩余0,完成)
- 计算指标:
- 平均等待时间 = [(15-0-8) + (4-1) + (26-2-9) + (19-3-5)] / 4 = (7+3+15+11)/4 = 9.0
- 平均周转时间 = [(19-0) + (7-1) + (26-2) + (24-3)] / 4 = (19+6+24+21)/4 = 17.5
- 时间片大小的权衡:
- 时间片太大→退化为FCFS,响应时间变差。
- 时间片太小→上下文切换开销过大,吞吐量下降。
- 经验法则:时间片应远大于上下文切换时间,但也不能太大(通常10-100ms)。
2.5 多级队列调度(MQ)
- 思想:将就绪队列划分为多个独立队列,每个队列有自己的调度算法。
- 典型划分:
- 系统进程:最高优先级
- 交互式进程:中等优先级,使用RR调度
- 批处理进程:最低优先级,使用FCFS调度
- 队列间调度:通常采用固定优先级抢占(只要高优先级队列有进程,就优先运行)或按时间比例分配。
第三部分:现代操作系统的实践——多级反馈队列(MLFQ)
MLFQ是当今操作系统(如UNIX、Linux、Windows)实际使用的调度算法的简化抽象,它结合了前面多种算法的优点。
3.1 MLFQ的设计目标
- 优化响应时间(针对交互式进程)
- 优化周转时间(针对批处理进程)
- 不需要预先知道进程的工作负载特性
3.2 MLFQ的基本规则
一个典型的MLFQ包含多个队列,每个队列有不同的优先级和不同的时间片:
- 规则1:如果A的优先级 > B的优先级,运行A。
- 规则2:如果A的优先级 = B的优先级,按RR轮转调度运行A和B。
- 规则3:新进程进入最高优先级队列。
- 规则4:进程在使用完其所在队列的整个时间片后,优先级降低(移入下一级队列)。
- 规则5:进程在时间片用完前主动放弃CPU(如进行I/O操作),优先级保持不变。
3.3 MLFQ的工作机制
假设一个三队列MLFQ:
- Q0:最高优先级,时间片=8ms
- Q1:中优先级,时间片=16ms
- Q2:最低优先级,时间片=FCFS
工作流程:
- 新进程P进入Q0,获得8ms时间片。
- 如果P在8ms内完成或主动放弃CPU,它保持在Q0(奖励交互式进程)。
- 如果P用完了8ms时间片,它被降级到Q1,获得16ms时间片。
- 如果P在Q1中又用完了16ms时间片,它被降级到Q2(FCFS)。
- 长时间运行的CPU密集型进程最终会沉入最低优先级队列,而短期的交互式进程会在高优先级队列快速完成。
3.4 MLFQ的优化:防止饥饿
基本MLFQ有一个问题:低优先级队列的进程可能饥饿。解决方案:
- 周期性地提升所有进程的优先级:例如,每秒钟将系统中所有进程都移到最高优先级队列。这保证了即使CPU密集型进程也能定期获得响应机会。
3.5 MLFQ的优势
- 无需预知:不需要知道进程是CPU密集型还是I/O密集型。
- 自适应性:能够自动识别并优待交互式进程。
- 平衡性:在各种工作负载下都能提供良好的性能。
第四部分:多处理器调度
现代系统大多是多核CPU,调度问题变得更加复杂:
4.1 对称多处理(SMP)与非对称多处理(AMP)
- SMP:每个处理器自我调度,共享就绪队列或各有私有队列。这是现代通用操作系统的标准。
- AMP:一个主处理器负责调度,其他处理器只执行计算任务。
4.2 多处理器调度的核心挑战
- 缓存亲和性:尽量让进程在同一个CPU核心上运行,这样可以重用仍在缓存中的数据,极大提升性能。
- 负载均衡:避免出现某些CPU核心极度繁忙而其他核心空闲的情况。
- 同步开销:多个调度器访问共享就绪队列时需要同步(锁),这可能成为性能瓶颈。
4.3 多处理器调度策略
- 单队列多处理器调度(SQMS):
- 所有CPU从一个共享就绪队列中取任务。
- 优点:自动负载均衡。
- 缺点:需要锁来保护队列,缓存亲和性差。
- 多队列多处理器调度(MQMS):
- 每个CPU有自己的就绪队列和自己的调度器。
- 优点:可扩展性好(无需锁),缓存亲和性好。
- 缺点:可能出现负载不均衡。
- 解决方案:迁移——定期检查各队列负载,在CPU间迁移任务以达到均衡。
总结与展望
今天我们深入探讨了:
- 调度算法的评估指标和决策时机
- 经典调度算法的优缺点:FCFS、SJF、优先级、RR
- 现代实践:多级反馈队列(MLFQ)的工作原理和优势
- 多处理器调度的特殊挑战和解决方案
调度算法的选择体现了操作系统设计的核心哲学:在各种相互冲突的目标之间寻找最佳平衡点。
系列导航:
- 上一篇:[操作系统入门] 第三章:进程与线程(一)—— 程序为何"运行"起来?
- 下一篇:[操作系统入门] 第五章:进程同步与通信——当多进程需要协作时

被折叠的 条评论
为什么被折叠?



