【操作系统入门】进程调度算法

【操作系统入门】第四章:进程调度算法——操作系统的大脑如何决策

本系列共10篇,这是第4/10篇。在第三章,我们理解了进程与线程的基本概念。今天,我们将深入操作系统最核心的决策机制——调度算法,探索CPU时间这个宝贵资源是如何被分配的。

开篇:调度——操作系统的终极决策难题

想象一下,你是机场的塔台调度员。眼前有数十架飞机等待起飞:有的载着数百名乘客,有的是紧急医疗航班,有的只是小型私人飞机。你只有一条跑道。你该让哪架飞机先飞?

这就是操作系统调度器面临的困境。CPU就像那条唯一的跑道,而进程/线程就是等待起飞的飞机。调度算法的选择,直接决定了整个系统的"用户体验"——是流畅响应还是卡顿不堪。


第一部分:调度基础——概念与指标

1.1 调度器的层次结构

现代操作系统的调度通常分为三个层次:

  • 长期调度(作业调度):决定哪些程序从磁盘被加载到内存中,变为就绪进程。控制系统的多道程序度
  • 中期调度:在内存紧张时,将某些进程暂时换出到磁盘(挂起),待条件允许时再换入。我们在内存管理章节会详述。
  • 短期调度(CPU调度):这是我们本章的重点——决定就绪队列中哪个进程/线程下一个获得CPU使用权

1.2 调度决策的发生时机

调度可能在以下时刻被触发:

  1. 进程从运行态转换为阻塞态(如I/O请求)
  2. 进程退出终止
  3. 进程从运行态转换为就绪态(如时间片用完、被更高优先级进程抢占)
  4. 进程从阻塞态转换为就绪态(如I/O完成)
  5. 时钟中断发生,检查是否需要调度

1.3 评估调度算法的关键指标

要评判一个调度算法的好坏,我们需要量化指标:

  • CPU利用率:CPU忙碌时间的百分比。理想情况下接近100%。
  • 吞吐量:单位时间内完成的进程数量。
  • 周转时间:从进程提交到进程完成的总时间(完成时间 - 到达时间)。
  • 等待时间:进程在就绪队列中等待的总时间。
  • 响应时间:从提交请求到第一次产生响应的时间(对交互式系统至关重要)。

调度算法的根本目标就是优化这些指标的组合。


第二部分:经典调度算法详解

让我们通过一个具体的例子来分析各种算法:假设有4个进程P1、P2、P3、P4,它们的到达时间和CPU执行时长(突发时间)如下:

进程到达时间突发时间
P108
P214
P329
P435

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的设计目标

  1. 优化响应时间(针对交互式进程)
  2. 优化周转时间(针对批处理进程)
  3. 不需要预先知道进程的工作负载特性

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

工作流程

  1. 新进程P进入Q0,获得8ms时间片。
  2. 如果P在8ms内完成或主动放弃CPU,它保持在Q0(奖励交互式进程)。
  3. 如果P用完了8ms时间片,它被降级到Q1,获得16ms时间片。
  4. 如果P在Q1中又用完了16ms时间片,它被降级到Q2(FCFS)。
  5. 长时间运行的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)的工作原理和优势
  • 多处理器调度的特殊挑战和解决方案

调度算法的选择体现了操作系统设计的核心哲学:在各种相互冲突的目标之间寻找最佳平衡点


系列导航:

  • 上一篇:[操作系统入门] 第三章:进程与线程(一)—— 程序为何"运行"起来?
  • 下一篇:[操作系统入门] 第五章:进程同步与通信——当多进程需要协作时
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

star _chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值