Skip to content

多级反馈队列调度

2026 大纲 二(二)4 CPU 调度算法多级反馈队列调度(MLFQ),它是多级队列允许"队列间移动"之后的改进版。指标口径与算例数据沿用 调度的基本概念与目标

交互可视化

加载可视化中...

可我事先并不知道这个进程是长是短

多级队列的分界很清楚:进程被永久分配到某条队列。 这就要求系统提前知道它是什么类型——交互的还是批处理的、长的还是短的。

可这个要求在真实系统里不成立。用户提交一个程序时,没人知道它要跑多久; SJF 也栽在同一件事上(它要预知服务时间)。

MLFQ 的解法很漂亮:不问,让它自己暴露。

具体做法是:新进程一律进最高优先级队列(先当短作业待遇), 在本级时间片内没跑完就降一级。于是—— 真正的短作业在高优先级队列里就跑完了,享受了最好的响应; 长作业会被一级级降下去,最终落到低优先级队列里慢慢跑。

"长短"这件事不再需要预知,而是由"被降级几次"这个事后行为自动区分, 而且分错了能自动纠正(一个先算很久后来转为交互的进程,会随着不再耗尽时间片而重新升上去)。

还有一处设计值得留意:优先级从高到低,时间片却从小到大。 理由是——能降到第 i 级,就说明它比前面各级都长, 既然注定要跑久,就给它更大的时间片,把切换开销摊薄

⚠️ 但 MLFQ 仍然可能饥饿:只有高优先级队列全部为空才轮到低优先级队列。 补丁是老化(等太久就提回高优先级)——注意它是补丁,不是基本规则。

一、降级与被抢占:本篇最容易搞混的一步

当进程正在第 i 级队列中运行时,若任一优先级更高的队列来了新进程,立即把当前进程放回到第 i 级队列的末尾,把 CPU 交给新到的高优先级进程。这与"时间片用完"对进程级别的影响完全相反:

时间片用完被抢占
触发该进程在本队列的时间片耗尽,仍未做完更高优先级队列来了新进程
它证明了什么这个进程确实比本级时间片长什么也没证明——它可能只跑了一瞬
处理降到下一级队列的队尾回到原队列的队尾,级别不变
下次运行时的时间片下一级的(更大)本级的,且是一个完整的新时间片

判据一句话:降级是"根据它已经跑掉多少"作出的判断,被抢占是"外部原因",与它自身的长短无关,所以不能拿来当降级依据。

时间片为什么从小到大

这条能推,不用背:

一个进程能降到第 i 级,说明它已经在前 i1 级各用完了一整个时间片却还没做完 ⇒ 它是长作业的证据在累积 ⇒ 长作业的特点是"需要很多 CPU、但对响应时间不敏感" ⇒ 给它更大的时间片,它一次能多做一些,总的切换次数减少 ⇒ 切换开销被摊薄。

反过来看最高级队列为什么时间片最小:那里挤满了刚到达的、还不知道长短的进程,给小时间片是为了让真正的短作业尽快做完就走,也让每个新进程都能很快得到第一次响应。若反过来从大到小,新到的短作业要么被大时间片里的长作业挡住,要么自己占着大时间片却用不完——两头都不讨好。

配合时间片轮转里的 q/(q+δ) 看更清楚:高优先级队列 q 小、切换损耗占比高,但那里的进程大多一两个时间片就走了,付出的总开销有限;低优先级队列 q 大、损耗占比低,正适合要长期占用 CPU 的进程。MLFQ 相当于对不同类型的进程用了不同的时间片,而分类是自动完成的。

二、老化:把"可能饥饿"补上

做法要素内容参数怎么定
触发条件一个进程在某队列中等待时间超过阈值 Θ也可实现为"每隔周期 Δ 全局扫描一次"
提升幅度提升一级,或直接提回最高级队列提一级更平滑,直接提回最高级更强力
配套动作提升后应重置它的等待计时;有的实现同时把所有进程一次性全部提回最高级队列(周期性重置)周期性重置实现最简单,但会周期性地丢失已积累的长短判断

这与优先级调度里的老化是同一个机制,只是那里改的是优先数、这里改的是队列号。

三、三个参数各自影响什么

参数调大调小影响的核心指标
队列数 k长短作业的分辨率更细;但一个长作业要经过更多次降级才沉到底,沉底速度慢分辨率粗,长短作业容易被混在同一级;k=1退化为 RR区分长短作业的精度
时间片倍率(下一级是上一级的几倍)低级队列切换开销摊得更薄;但低级队列里的进程一旦上 CPU 就占用很久,同级其他进程的响应变差切换更频繁,q/(q+δ) 下降低级队列的切换开销 vs 同级响应
老化阈值 Θ防饥饿变弱,低级进程实际等待时间长所有进程很快被提回高级队列,长短作业的区分被冲掉,退化为 RR防饥饿强度 vs 区分能力

四、MLFQ 好在哪里,以及与多级队列的分界

优点说明由哪条规则给出
无需预知服务时间靠"降了几级"这个事后行为自动区分长短规则 ③
无需提前分类不像多级队列那样要先知道进程类型规则 ② + ③
对短作业友好短作业在高优先级队列(时间片小、优先级高)就能完成规则 ① + ②
响应时间极好新进程一律进最高级队列,几乎立刻得到第一次服务规则 ②
对长作业仍公平长作业虽降级,但最终会在低级队列得到执行;配合老化则等待有上界规则 ⑤ + 老化
⚠️ 可能饥饿高优先级队列持续有新进程时,低级长作业长期得不到调度规则 ④;靠老化缓解
特性多级队列多级反馈队列
队列间移动不允许允许(降级 + 老化升级)
预先分类必须提前确定进程类型不需要,自动分类
分类依据进程的静态类型(系统/交互/批处理)进程的动态行为(跑了几个时间片)
分类错了怎么办无法纠正,一错到底自动纠正(行为变了级别就会变)

这张表其实只有第一行是独立的,后面三行都是它的推论。

逐步推演:每一步标出这是"降级"还是"被抢占",以及与其他六种算法的横向对比(想在时间轴上看清进程怎么一级级沉下去时展开)

三级队列,Q1 的 q=1、Q2 的 q=2、Q3 内部 FCFS 不再降级。约定:被抢占的进程回原队列末尾,下次调度时重新获得一个完整时间片同级队列之间不发生抢占

进程到达时间服务时间
P107
P224
P341
P454
时间运行在哪一级本次跑了结束原因去向各队列状态(运行后)
0–1P1Q11时间片用完降到 Q2Q1:[] Q2:[P1]
1–2P1Q21被抢占(t=2 时 P2 进 Q1)回 Q2 队尾Q1:[P2] Q2:[P1]
2–3P2Q11时间片用完降到 Q2Q1:[] Q2:[P1,P2]
3–4P1Q21被抢占(t=4 时 P3 进 Q1)回 Q2 队尾Q1:[P3] Q2:[P2,P1]
4–5P3Q11做完完成Q1:[P4] Q2:[P2,P1]
5–6P4Q11时间片用完降到 Q2Q1:[] Q2:[P2,P1,P4]
6–8P2Q22时间片用完降到 Q3Q2:[P1,P4] Q3:[P2]
8–10P1Q22时间片用完降到 Q3Q2:[P4] Q3:[P2,P1]
10–12P4Q22时间片用完降到 Q3Q2:[] Q3:[P2,P1,P4]
12–13P2Q31做完完成Q3:[P1,P4]
13–15P1Q32做完完成Q3:[P4]
15–16P4Q31做完完成

两处最值得停下来看的地方

  • t=1–2 与 t=3–4:P1 两次在 Q2 里只跑了 1 个单位就被抢占,两次都回到 Q2 而不是降到 Q3。它真正被降到 Q3 是在 t=8–10 那次——那次它用完了 Q2 完整的 2 个单位。
  • P4 于 t=5 到达、t=5 就上了 CPU:因为新进程一律进最高优先级队列,而此刻 Q1 恰好只有它。
区间0–22–33–44–55–66–88–1010–1212–1313–1515–16
进程P1P2P1P3P4P2P1P4P2P1P4
进程完成时间周转时间带权周转时间等待时间响应时间
P1151515/7 ≈ 2.1480
P2131111/4 = 2.7570
P3511/1 = 1.0000
P4161111/4 = 2.7570
平均9.502.165.500.00

四个进程的响应时间全是 0,这不是巧合:新进程一律进最高优先级队列,而更高优先级队列里没有别人,所以它一到达就能上 CPU。

算法平均周转平均带权周转平均响应
FCFS8.753.504.75
SJF(非抢占)8.002.564.00
SRTF(抢占)7.001.510.50
RR(q=29.002.381.50
优先级(抢占)9.004.103.00
MLFQ9.502.160.00

读法:MLFQ 的平均周转时间在这组数据里并不出众,但它的响应时间是全场最好的 0.00,而且它是唯一一个不需要预知服务时间、也不需要提前给进程分类就能做到这一点的算法。SRTF 的周转最优,但它要求预知服务时间——这个前提在真实系统里拿不到。

考点速记

  1. MLFQ 的核心规则优先级从高到低、时间片从小到大新进程一律进最高级队列本级时间片内没跑完就降一级
  2. ⚠️时间片从小到大是有理由的:能降到第 i 级,就说明它比前面各级都长;既然注定要跑久,就给更大的时间片摊薄切换开销
  3. ⚠️被抢占与时间片用完必须分清时间片用完 → 降一级被更高优先级进程抢占 → 回原队列队尾、级别不变
  4. ⚠️只有高优先级队列全部为空才调度低优先级队列,因此 MLFQ 仍可能饥饿;靠老化补上(k 级、阈值 Θ 时等待上界 kΘ)。老化是补丁不是基本规则。
  5. MLFQ 不需要预知服务时间、也不需要提前分类——长短由"被降级几次"这一事后行为自动区分,而且分类错了能自动纠正(先算很久后来转为交互的进程会重新升上去)。
  6. 三个参数(队列数、时间片倍率、老化阈值)调到极端都会塌回 RR

这一节在真题里被考过的形式

两道题,一道手算、一道问设计要素。

  • 给二级反馈队列的参数与各进程的到达和执行时间,算等待时间或完成时刻(2019-27)。⚠️ 手算时最容易漏的两处:"降级"发生在时间片用完的那一刻(不是跑完的时刻)、被抢占回到原队列队尾而不降级(速记第三条)。另外要看清题目给的各级时间片分别是多少——它们通常不等。
  • 问设计多级反馈队列调度算法时要考虑哪些因素(2020-26,在调度的基本概念讲)。答四条全部:就绪队列的数量、各队列的优先级、各队列的调度算法、进程在队列间的迁移条件。⚠️最后一条正是它区别于多级队列的地方(多级队列不迁移,所以不需要定这一条)。

复习优先级必须拿满,手算要练。 第三条(降级 vs 被抢占)是手算题唯一的技术难点; 第五条(不需要预知服务时间)是 MLFQ 相对 SJF 的最大卖点,也是概念题的落点。 第四条(仍可能饥饿、靠老化补)容易被误判成"MLFQ 不会饥饿",要单独记。

易错:认为进程被抢占后也要降一级。只有时间片用完才降级;被抢占是回原队列队尾。

易错:认为 MLFQ 不会饥饿。——高优先级队列一直不空,低优先级就一直排不上,靠老化补救。

易错:认为各级队列的时间片一样大。从小到大——越低级时间片越大,为的是摊薄切换开销。

易错:认为 MLFQ 需要提前知道进程是长是短。不需要——靠"被降级几次"事后自动区分。

易错:把老化当成 MLFQ 的基本规则。它是防饥饿的补丁,不是那五条核心规则之一。

教材出处
  • 汤小丹《计算机操作系统》3.3.5 多级反馈队列调度算法(多个就绪队列、优先级最高的队列时间片最小且下一级是上一级的两倍、新进程放入第一队列末尾、时间片内未完成则转入下一队列末尾、仅当第 1~(i−1) 队列均空才调度第 i 队列、运行中若更高优先级队列来了新进程则把当前进程放回第 i 队列末尾),印刷 p95–p96

相关知识

调度的基本概念与目标多级队列调度公平调度算法优先级调度时间片轮转调度SJF 短作业优先调度

真题练习