Files
obsidian/操作系统/11_处理机调度/11_处理机调度.md
T

20 KiB
Raw Blame History

11 处理机调度

课程:操作系统 关联章节:06_进程控制 | 12_死锁


一、处理器调度的概念

1.1 什么是调度

处理器调度的核心任务是将 CPU 时间 公平、合理地分配给系统中的各个进程。其本质是一种资源分配决策——决定在某一时刻,哪个进程获得 CPU 的使用权。

类比:学校排课——教室(CPU)有限,多个班级(进程)都要使用,需要教务处(调度器)制定合理的课表。

1.2 调度的基本原则

原则 说明
公平性 每个进程都能获得合理的 CPU 时间
高效性 CPU 利用率尽可能高
响应性 交互式进程能快速得到响应
吞吐量 单位时间内完成的进程数尽可能多

二、作业(Job)的概念

2.1 作业与作业步

  • 作业(Job):用户提交给系统的一项完整工作,是系统进行资源分配的基本单位。
  • 作业步(Job Step):作业中若干个既独立又相互关联的加工步骤。每个作业步完成一项特定的处理任务。
作业示例:编写并运行一个C程序
  作业步1:编辑(edit)→ 生成源代码文件
  作业步2:编译(compile)→ 生成目标文件
  作业步3:链接(link)→ 生成可执行文件
  作业步4:运行(run)→ 输出结果

2.2 作业的状态转换

stateDiagram-v2
    [*] --> 后备 : 用户提交作业
    后备 --> 运行 : 高级调度(被选中)
    运行 --> 完成 : 作业执行结束
    完成 --> [*] : 撤离系统

    state 运行 {
        [*] --> 就绪 : 进程创建
        就绪 --> 执行 : 低级调度(被选中)
        执行 --> 就绪 : 时间片用完
        执行 --> 阻塞 : 等待I/O
        阻塞 --> 就绪 : I/O完成
    }

2.3 作业控制块(JCB)

作业控制块是作业在系统中存在的唯一标识,包含:

  • 作业名、作业状态
  • 资源需求(内存大小、外设类型等)
  • 优先级、提交时间
  • 作业步信息

三、三级调度体系

graph TB
    subgraph 外存
        A[后备队列<br/>作业池]
    end

    subgraph 内存
        B[就绪队列]
        C[阻塞队列]
        D[CPU 执行]
    end

    A -->|高级调度<br/>长程调度<br/>作业调度| B
    B -->|低级调度<br/>短程调度<br/>进程调度| D
    D -->|时间片用完/等待事件| B
    D -->|等待I/O| C
    C -->|I/O完成| B

    B -->|中级调度<br/>交换调度<br/>内存调度| A

    style A fill:#f9f,stroke:#333
    style D fill:#ff9,stroke:#333
调度级别 别名 频率 功能
高级调度 作业调度 / 长程调度 最低 从后备队列选择作业调入内存
中级调度 交换调度 / 内存调度 中等 将暂时不用的进程换出到外存(挂起)
低级调度 进程调度 / 短程调度 最高 从就绪队列选择进程分配 CPU

四、调度时机

4.1 何时触发调度

flowchart TD
    A{发生什么事件?} --> B[进程结束]
    A --> C[进程等待事件<br/>如I/O请求]
    A --> D[时间片用完]
    A --> E[新进程产生]
    A --> F[等待的事件已发生<br/>如I/O完成]

    B --> G[执行调度]
    C --> G
    D --> G
    E --> G
    F --> G

    G --> H[选择下一个<br/>运行的进程]

    style G fill:#ff9,stroke:#333
调度时机 说明 触发场景
进程结束 运行进程执行完毕 正常退出
等待事件 进程因 I/O 等阻塞 读磁盘、等待键盘输入
时间片用完 当前进程的时间配额耗尽 时钟中断
新进程产生 新进程进入就绪队列 fork() 创建子进程
等待事件已发生 阻塞进程变就绪 I/O 中断

五、调度方式

5.1 非抢占式调度

进程自愿放弃 CPU,系统不会强制剥夺。只有当进程结束、阻塞或主动让出时才调度。

  • 优点:实现简单,系统开销小
  • 缺点:响应时间不可预测,不适合交互式系统

5.2 抢占式调度

系统强制剥夺当前运行进程的 CPU,分配给其他进程。

  • 优点:响应快,适合分时/实时系统
  • 缺点:实现复杂,需要保存/恢复现场,开销较大
graph LR
    subgraph 非抢占式
        A[进程A运行] -->|自愿放弃| B[调度]
        B --> C[进程B运行]
    end

    subgraph 抢占式
        D[进程A运行] -->|强制剥夺| E[调度]
        E --> F[进程B运行]
    end

    style E fill:#f96,stroke:#333

六、调度算法的设计目标

系统类型 主要目标 关键指标
批处理系统 周转时间短、吞吐量高 平均周转时间、吞吐量
分时系统 响应时间快、均衡性 响应时间、公平性
实时系统 满足截止时间、可预测性 截止时间满足率

关键性能指标

\text{周转时间} = \text{完成时间} - \text{提交时间} \text{等待时间} = \text{周转时间} - \text{运行时间} \text{带权周转时间} = \frac{\text{周转时间}}{\text{运行时间}}

七、批处理调度算法

7.1 FCFS — 先来先服务

First Come First Served:按进程到达就绪队列的先后顺序依次调度。

示例

假设三个进程 P1、P2、P3 几乎同时到达:

进程 运行时间
P1 24
P2 3
P3 3

按 P1→P2→P3 顺序执行:

时间轴(Gantt图):
|--------P1(24)--------|--P2(3)--|--P3(3)--|
0                      24       27       30
进程 完成时间 周转时间 等待时间
P1 24 24 0
P2 27 27 24
P3 30 30 27
平均 27 17

按 P2→P3→P1 顺序执行(短作业在前):

时间轴(Gantt图):
|--P2(3)--|--P3(3)--|--------P1(24)--------|
0         3         6                      30
进程 完成时间 周转时间 等待时间
P2 3 3 0
P3 6 6 3
P1 30 30 6
平均 13 3

结论:FCFS 对短作业非常不利,平均等待时间从 17 降到仅 3(仅调整顺序)。

7.2 SJF — 短作业优先

Shortest Job First:选择估计运行时间最短的进程优先执行。

两种变体

graph TD
    A[SJF 短作业优先] --> B[非抢占式 SJF]
    A --> C[抢占式 SJF<br/>即 SRTF]

    B --> D[进程开始执行后<br/>不会被中断]
    C --> E[新进程到达时<br/>比较剩余时间<br/>更短则抢占]

    style C fill:#f96,stroke:#333

示例(非抢占式 SJF)

进程 到达时间 运行时间
P1 0 7
P2 2 4
P3 4 1
P4 5 4
Gantt图(非抢占SJF):
|--P1(7)--|-P3(1)-|---P2(4)---|---P4(4)---|
0         7       8          12          16
  • t=0 时只有 P1,P1 先执行
  • t=7 时 P2、P3、P4 都已到达,选最短的 P3(运行时间 1)
  • t=8 时选 P2(运行时间 4)
  • t=12 时选 P4

示例(抢占式 SRTF)

进程 到达时间 运行时间
P1 0 7
P2 2 4
P3 4 1
P4 5 4
Gantt图(抢占式SRTF):
|--P1--|P1|P3|---P2---|---P4---|--P1--|
0      2  4  5       9       13     16

时间线:
0-2: P1运行(剩5)
2: P2到达(需4) < P1剩余(5), P2抢占
2-4: P2运行(剩2)
4: P3到达(需1) < P2剩余(2), P3抢占
4-5: P3完成
5: P4到达(需4) = P2剩余(2), P2先到
5-7: P2完成(剩2)
7: P4(需4) vs P1(剩5), P4更短
7-11: P4完成
11-16: P1完成(剩5)
进程 完成时间 周转时间 等待时间
P1 16 16 9
P2 9 7 3
P3 5 1 0
P4 13 8 4
平均 8 4

SJF 的优缺点

优点 缺点
平均等待时间最小(理论上最优) 对长作业不利,可能产生饥饿
吞吐量高 需要预知运行时间(难以精确估计)

7.3 HRRF — 响应比高优先

Highest Response Ratio First:FCFS 和 SJF 的折衷方案。

\text{响应比} = 1 + \frac{\text{等待时间}}{\text{估计运行时间}}
  • 短作业:运行时间小,响应比容易变高 → 兼顾 SJF
  • 长作业:随着等待时间增长,响应比逐渐增大 → 避免饥饿
flowchart LR
    A[选择响应比最高的进程] --> B{响应比 = 1 + 等待时间/运行时间}
    B --> C[短作业:等待时间相同时<br/>运行时间短 → 响应比高]
    B --> D[长作业:等待时间越长<br/>响应比越高 → 不会饥饿]

示例

进程 到达时间 运行时间
P1 0 20
P2 0 5
P3 0 10

t=0: 三个进程同时到达,计算响应比:

  • P1: 1 + 0/20 = 1
  • P2: 1 + 0/5 = 1
  • P3: 1 + 0/10 = 1

全部相同,按 FCFS 选 P1(运行时间 20)。

t=20: P1 完成,计算剩余进程响应比:

  • P2: 1 + 20/5 = 5
  • P3: 1 + 20/10 = 3

选 P2(响应比 5),P2 执行到 t=25。

t=25: 选 P3(响应比 1+25/10=3.5),P3 执行到 t=35。

7.4 优先级调度

Priority Scheduling:为每个进程分配优先级,选择优先级最高的进程执行。

分类方式 说明
静态优先级 创建时确定,运行期间不变
动态优先级 运行期间根据情况调整
抢占式 高优先级进程到达时可抢占当前进程
非抢占式 等当前进程完成后才重新调度

八、分时调度算法

8.1 RR — 时间片轮转

Round Robin:就绪队列中的进程按先来先服务依次执行,每个进程每次最多运行一个时间片(quantum)的时间。

示例

4 个进程,时间片 q = 4:

进程 到达时间 运行时间
P1 0 24
P2 0 3
P3 0 3
P4 0 6
Gantt图(时间片q=4):
|P1(4)|P2(3)|P3(3)|P4(4)|P1(4)|P4(2)|P1(4)|P1(4)|P1(4)|P1(4)|
0     4     7    10    14    18    20   24    28    32    36

执行顺序:
0-4:   P1执行(剩20)
4-7:   P2执行(完成) ← P2只需3 < 时间片4
7-10:  P3执行(完成) ← P3只需3 < 时间片4
10-14: P4执行(剩2)
14-18: P1执行(剩16)
18-20: P4执行(完成) ← P4剩2 < 时间片4
20-24: P1执行(剩12)
24-28: P1执行(剩8)
28-32: P1执行(剩4)
32-36: P1执行(完成)
进程 完成时间 周转时间 等待时间
P1 36 36 12
P2 7 7 4
P3 10 10 7
P4 20 20 14
平均 18.25 9.25

时间片大小的影响

graph TD
    A[时间片 q 的选择] --> B[q 太大]
    A --> C[q 太小]
    A --> D[q 适中]

    B --> E[退化为 FCFS<br/>响应时间变长]
    C --> F[进程切换频繁<br/>系统开销过大]
    D --> G[兼顾响应性和效率<br/>通常 10~100ms]

    style B fill:#f99,stroke:#333
    style C fill:#f99,stroke:#333
    style D fill:#9f9,stroke:#333

时间片选择示例

10 个进程,进程切换开销为 10ms。

  • 时间片 q = 200ms:每个进程切换一次,总切换时间 = 10×10ms = 100ms
    • 开销比 = 100 / (10×200) = 5% → 可接受
  • 时间片 q = 100ms:每个进程切换约2次,总切换时间 = 20×10ms = 200ms
    • 开销比 = 200 / (10×200) = 10% → 开销偏高

8.2 多级反馈队列(MFQ)

Multi-level Feedback Queue:综合多种调度算法优点的经典调度算法。

graph TB
    subgraph MFQ多级反馈队列
        A[新进程到达] --> B[队列1<br/>优先级最高<br/>时间片最小 如4ms]
        B -->|时间片用完<br/>未完成| C[队列2<br/>优先级中等<br/>时间片中等 如8ms]
        C -->|时间片用完<br/>未完成| D[队列3<br/>优先级最低<br/>时间片最大 如16ms]
    end

    B -->|完成| E[进程结束]
    C -->|完成| E
    D -->|完成| E

    B -->|等待I/O| F[阻塞]
    F -->|I/O完成| B

    style B fill:#9f9,stroke:#333
    style C fill:#ff9,stroke:#333
    style D fill:#f99,stroke:#333

MFQ 的核心规则

  1. 新进程进入最高优先级队列(队列1)
  2. 进程在当前队列用完时间片 → 降级到下一优先级队列
  3. 高优先级队列空时,才调度低优先级队列
  4. 可设置队列间调度策略:固定优先级 或 按时间比例分配
特点 说明
自适应 I/O 密集型进程常在高优先级队列(因时间片未用完就阻塞)
周转时间短 CPU 密集型进程最终会降到低优先级队列,用大时间片执行
公平性 各类用户(交互型、批处理型)都能得到合理服务

九、实时调度算法

9.1 EDF — 最早截止时间优先

Earliest Deadline First:截止时间越早的进程,优先级越高。

gantt
    title EDF 调度示例
    dateFormat X
    axisFormat %s

    section 进程
    P1(截止t=4) :a1, 0, 2
    P2(截止t=6) :a2, 2, 5
    P3(截止t=8) :a3, 5, 7
进程 到达时间 运行时间 截止时间
P1 0 2 4
P2 0 3 6
P3 0 2 8

调度过程:

  1. t=0:P1(截止4) < P2(截止6) < P3(截止8) → 执行 P1
  2. t=2:P1 完成,P2(截止6) < P3(截止8) → 执行 P2
  3. t=5:P2 完成,执行 P3
  4. t=7:全部完成,均满足截止时间

9.2 LLF — 最低松弛度优先

Least Laxity First:选择松弛度最小的进程优先执行。

\text{松弛度} = \text{必须完成时间} - \text{本身运行时间} - \text{当前时间}

松弛度越小,说明该进程越"紧迫"。

示例

进程 运行时间 截止时间
P1 2 8
P2 4 12

t=0 时刻:

  • P1 松弛度 = 8 - 2 - 0 = 6
  • P2 松弛度 = 12 - 4 - 0 = 8

P1 松弛度更小,先执行 P1。


十、优先级倒置问题

10.1 问题描述

优先级倒置(Priority Inversion):高优先级进程被低优先级进程间接阻塞的现象。

sequenceDiagram
    participant H as 高优先级进程H
    participant M as 中优先级进程M
    participant L as 低优先级进程L
    participant R as 共享资源R

    L->>R: 获得资源R(加锁)
    H->>R: 请求资源R → 阻塞!
    Note over H: H必须等待L释放R
    M->>M: M到达,优先级高于L
    Note over M: M抢占L执行
    Note over H: H被M间接阻塞!<br/>优先级倒置发生!
    M->>M: M执行完毕
    L->>R: 释放资源R
    H->>R: 获得资源R,继续执行

10.2 解决方案——优先级继承

Priority Inheritance Protocol:当高优先级进程因共享资源阻塞时,临时提升持有该资源的低优先级进程的优先级,使其尽快完成并释放资源。

sequenceDiagram
    participant H as 高优先级进程H
    participant L as 低优先级进程L(提升优先级)
    participant M as 中优先级进程M
    participant R as 共享资源R

    L->>R: 获得资源R
    H->>R: 请求资源R → 阻塞
    Note over L: L的优先级临时提升为H的优先级
    Note over M: M到达,但L优先级已提升
    Note over M: M无法抢占L!
    L->>R: 释放资源R
    Note over L: L优先级恢复原值
    H->>R: 获得资源R,继续执行

十一、Linux 调度器

11.1 CFS — 完全公平调度器

Completely Fair Scheduler:Linux 默认调度器,基于**虚拟运行时间(vruntime)**实现公平调度。

核心思想:vruntime 最小的进程优先执行。

\text{vruntime} += \text{实际运行时间} \times \frac{\text{nice 值基准权重}}{\text{该进程权重}}
graph TD
    A[CFS调度器] --> B{选择 vruntime<br/>最小的进程}
    B --> C[红黑树组织<br/>就绪进程]
    C --> D[最左叶子节点<br/>= vruntime 最小]
    D --> E[执行该进程]
    E --> F[更新 vruntime]
    F --> C

    style D fill:#9f9,stroke:#333

CFS 特点

特性 说明
无固定时间片 根据进程权重和系统负载动态计算
红黑树结构 O(log n) 插入/查找,高效调度
公平性保证 nice 值越低(优先级越高),vruntime 增长越慢
自动适配 I/O 密集型进程 vruntime 自然较小,获得更多 CPU

11.2 调度器类层次

graph TB
    A[调度器类优先级] --> B[Stop Task<br/>最高优先级<br/>停止特定CPU]
    A --> C[Real-Time<br/>实时调度类]
    A --> D[Fair<br/>CFS 调度类<br/>普通进程]
    A --> E[Idle Task<br/>最低优先级<br/>空闲任务]

    B --> C --> D --> E

    style B fill:#f66,stroke:#333
    style C fill:#f96,stroke:#333
    style D fill:#9f9,stroke:#333
    style E fill:#99f,stroke:#333

调度顺序:Stop Task > Real-Time > Fair > Idle Task

每次调度时,优先从高优先级调度类中选择进程。

11.3 实时进程调度策略

策略 说明
SCHED_FIFO 先来先服务。实时进程一旦获得 CPU,将一直执行直到主动放弃或被更高优先级进程抢占
SCHED_RR 时间片轮转。同优先级的实时进程轮流使用 CPU,时间片用完后回到队尾

十二、调度算法对比总结

graph LR
    subgraph 批处理算法
        FCFS[FCFS<br/>简单公平]
        SJF[SJF/SRTF<br/>最优平均等待]
        HRRF[HRRF<br/>FCFS+SJF折衷]
        PRIO[优先级调度<br/>灵活控制]
    end

    subgraph 分时算法
        RR[RR 轮转<br/>公平响应]
        MFQ[多级反馈队列<br/>综合最优]
    end

    subgraph 实时算法
        EDF[EDF<br/>截止时间优先]
        LLF[LLF<br/>松弛度优先]
    end

    FCFS -.->|缺点: 短作业等待久| SJF
    SJF -.->|缺点: 长作业饥饿| HRRF
    RR -.->|时间片选择关键| MFQ
算法 类型 抢占 优点 缺点
FCFS 批处理 否 简单公平 短作业等待时间长
SJF 批处理 否 最小平均等待 长作业饥饿
SRTF 批处理 是 更优的平均等待 长作业饥饿
HRRF 批处理 否 兼顾公平 需预估运行时间
RR 分时 是 响应快 时间片选择影响大
MFQ 分时 是 自适应各类进程 参数调整复杂
EDF 实时 是 利用率可达100% 过载时不确定
LLF 实时 是 松弛度精确 频繁切换开销

十三、本讲关键公式

\text{周转时间} = \text{完成时间} - \text{提交时间} \text{等待时间} = \text{周转时间} - \text{运行时间} \text{带权周转时间} = \frac{\text{周转时间}}{\text{运行时间}} \geq 1 \text{平均周转时间} = \frac{1}{n}\sum_{i=1}^{n}T_i \text{响应比} = 1 + \frac{\text{等待时间}}{\text{估计运行时间}} \text{松弛度} = \text{必须完成时间} - \text{本身运行时间} - \text{当前时间} \text{时间片开销比} = \frac{\text{进程数} \times \text{切换时间}}{\text{进程数} \times \text{时间片}} = \frac{\text{切换时间}}{\text{时间片}}

十四、常见考点

  1. FCFS/SJF/RR 手工计算:给定进程到达时间和运行时间,画 Gantt 图,计算平均等待时间和周转时间
  2. 时间片大小对 RR 的影响:太大退化为 FCFS,太小切换开销大
  3. 响应比计算:HRRF 的每一步调度决策
  4. 优先级倒置场景分析及优先级继承原理
  5. CFS 核心思想:vruntime 最小优先

上一章:06_进程控制 下一章:12_死锁