操作系统 进程(3)进程调度算法
目标问题:
“系统如何决定下一个运行的进程是谁?”
学习重点:
-
调度的三种场景(抢占式 / 非抢占式 / 实时)
-
各种经典算法:
- FCFS(先来先服务)
- SJF(短作业优先)
- RR(时间片轮转)
- 优先级调度
- 多级反馈队列(MLFQ)
-
性能指标:吞吐量、周转时间、响应时间
📘 建议练习:
手算一组进程调度表(5个进程,分别有不同的到达时间与运行时间),模拟RR和SJF结果并比较。
🧩 一、调度的基本概念
操作系统中,CPU 同时面对多个「就绪态」的进程。
这时就需要“调度器(Scheduler)”来挑选一个进程分配 CPU。
调度发生的时机主要有三种:
场景 | 举例 | 是否允许“打断”正在运行的进程 |
---|---|---|
非抢占式调度 | 一个进程执行完或主动阻塞(如I/O)后,系统才挑下一个 | ❌ 不允许打断 |
抢占式调度 | 系统根据规则(如时间片耗尽或更高优先级出现)强制切换 | ✅ 允许打断 |
实时调度 | 某些任务有严格时间要求(如心跳监控、传感器读数) | ✅ 必须保障响应时间 |
⚙️ 二、经典调度算法
1️⃣ FCFS(First Come First Serve,先来先服务)
特点:
- 谁先进入就绪队列,谁先执行。
- 非抢占式。
- 简单,但可能导致“长作业拖慢短作业”(队头阻塞问题)。
示例:
进程 | 到达时间 | 运行时间 |
---|---|---|
P1 | 0 | 6 |
P2 | 2 | 4 |
P3 | 4 | 2 |
🧮 调度顺序:P1 → P2 → P3
- P1: 0-6
- P2: 6-10
- P3: 10-12
平均周转时间 = (6 + 8 + 8)/3 = 7.33
缺点:后面的小进程要等前面的大进程。
2️⃣ SJF(Shortest Job First,短作业优先)
特点:
- 谁的执行时间最短,谁先执行。
- 非抢占式(基本版本)。
- 理论上平均等待时间最短,但需要预知执行时间(难点!)。
同样的数据:
进程 | 到达时间 | 运行时间 |
---|---|---|
P1 | 0 | 6 |
P2 | 2 | 4 |
P3 | 4 | 2 |
🧮 调度顺序:P1(0-6),P3(6-8),P2(8-12)
平均周转时间 = (6 + 10 + 4)/3 = 6.67
比 FCFS 稍好,但不公平,可能饿死长作业。
3️⃣ RR(Round Robin,时间片轮转)
特点:
- 每个进程轮流获得固定 CPU 时间(时间片)。
- 若没执行完就让出 CPU,进入队列尾。
- 抢占式。
- 公平,适合交互式系统。
示例:
进程 | 到达时间 | 运行时间 |
---|---|---|
P1 | 0 | 5 |
P2 | 1 | 3 |
P3 | 2 | 1 |
时间片 = 2
🧮 调度过程:
时间轴:P1(0-2), P2(2-4), P3(4-5), P1(5-7), P2(7-8), P1(8-9)
→ 所有人都轮流执行
优点:响应快、公平
缺点:时间片太短则频繁切换(开销大)
4️⃣ 优先级调度(Priority Scheduling)
特点:
- 每个进程分配优先级(数值越高或越低越重要)。
- CPU 每次选择优先级最高的。
- 可抢占式,也可非抢占式。
- 缺点:低优先级可能长期得不到执行(饥饿问题)。
解决方法:
动态调整优先级(等待时间越久,优先级逐渐提升)。
5️⃣ 多级反馈队列(MLFQ)
💡 现代操作系统最常用算法!
思想:
- 综合了前面所有算法的优点;
- 动态地**“奖励短任务,惩罚长任务”**;
- CPU 不再固定给时间片,而是根据进程行为变化:
队列等级 | 时间片 | 调度规则 |
---|---|---|
Q1 | 8ms | 最高优先级,短任务快速响应 |
Q2 | 16ms | 普通任务 |
Q3 | 32ms | 长任务或后台任务 |
调度逻辑:
- 新进程 → 放入 Q1
- 若 Q1 时间片没执行完 → 降级到 Q2
- 若 Q2 仍没完 → 再降到 Q3
- 一旦 I/O 完成或长时间等待 → 优先级上升(防饿死)
🧠 核心思想:时间片可变 + 动态优先级调整
📊 三、性能指标
指标 | 含义 | 希望的方向 |
---|---|---|
吞吐量 | 单位时间内完成的进程数 | 越高越好 |
周转时间 | 从提交到完成的时间 | 越短越好 |
等待时间 | 进程在就绪队列中等待的时间 | 越短越好 |
响应时间 | 第一次获得CPU的等待时间 | 越短越好 |