Skip to content

公平调度算法

2026 大纲 二(二)4 CPU 调度算法里以公平性为目标的两个算法:保证调度(对进程公平)与公平分享调度(对用户公平)。指标口径沿用 调度的基本概念与目标

前面七种都在承诺次序,这一种承诺份额

回头看前面七种算法,它们承诺的东西其实是同一类:次序。 FCFS 承诺"按来的顺序",SJF 承诺"短的先跑",RR 承诺"轮着来", 优先级承诺"重要的先跑",MLFQ 承诺"短的自动优先"。

次序解决不了一个问题:我到底能分到多少 CPU? 在 RR 下,进程数一多,每个人分到的都变少,但没人告诉你会变成多少。

公平调度换了个承诺:不承诺你什么时候跑,承诺你能拿到多少。

保证调度为每个进程保证约 1/n 的处理机时间,做法是给每个进程算一个 公平比率 = 实际获得的时间 ÷ 应当获得的时间,每次挑比率最小的那个。 比率小于 1 说明系统欠它、大于 1 说明它超额了。

用比值而不用差值是有理由的:差值没法在应得份额不同的进程之间比较, 比值把欠账折算成了相对于自身应得份额的比例

还有一个附带的好处:分母(应得时间)随时间单调增长, 所以一个进程只要一直没跑,它的比率就会一直往下掉,早晚被选中—— 它天然不饥饿,也不需要老化补丁。老化被内建进了比较键里。

⚠️ 最后一处要分清:对进程公平不等于对用户公平。 进程数是用户自己决定的——一个用户开 10 个进程,就能拿走 10 份。 公平分享调度因此改按用户分配份额,本质是按用户加权的 RR

一、保证调度算法

实现分五步:

步骤做什么
跟踪计算每个进程自创建以来已经执行的处理时间(实际获得)
计算每个进程应获得的 CPU 时间 = (当前时刻 − 创建时刻)/ n
计算公平比率 = 实际获得 / 应获得
比较各进程的公平比率
调度比率最小的进程,让它一直运行,直到它的比率超过最接近它的那个进程为止
公平比率=进程实际获得的 CPU 时间应获得的 CPU 时间=已执行时间(t创建时刻)/n
三进程的公平比率逐步演算:超额者怎么被晾住、又怎么自己回到队首(想看比率如何随时间收敛时展开)

n=3,创建时刻分别为 A: 0、B: 2、C: 4。到 t=6 时三者已获得的 CPU 时间为 A: 4、B: 1、C: 0。以 1 个时间单位为粒度重算并调度,列出 t=6 起 8 步。

每一步都做同一件事:先算三个进程各自的"应得",再用"实得 ÷ 应得"得到比率,选比率最小者运行 1 个单位。

tA 实得/应得 = 比率B 实得/应得 = 比率C 实得/应得 = 比率选中
64 / (6−0)/3 = 4/2 = 2.0001 / (6−2)/3 = 1/(4/3) = 0.7500 / (6−4)/3 = 0/(2/3) = 0.000C
74 / (7/3) = 1.7141 / (5/3) = 0.6001 / 1 = 1.000B
84 / (8/3) = 1.5002 / 2 = 1.0001 / (4/3) = 0.750C
94 / 3 = 1.3332 / (7/3) = 0.8572 / (5/3) = 1.200B
104 / (10/3) = 1.2003 / (8/3) = 1.1252 / 2 = 1.000C
114 / (11/3) = 1.0913 / 3 = 1.0003 / (7/3) = 1.286B
124 / 4 = 1.0004 / (10/3) = 1.2003 / (8/3) = 1.125A
135 / (13/3) = 1.1544 / (11/3) = 1.0913 / 3 = 1.000C

演算完成后累计获得的 CPU 时间为 A: 5、B: 4、C: 4。三处值得停下来看:

  1. t=6 时 A 的比率高达 2.000,此后连续 6 步都没被调度,直到 t=12 才轮到它。这就是"超额者暂缓"的实际形态:不是惩罚,只是让别人先把欠账补上。
  2. A 的比率从 2.000 一路降到 1.000,它什么也没做——分母随时间增长而分子不变。这正是保证调度的自我修正机制,也是它天然不饥饿的原因。
  3. 三个比率在收敛:从 (2.000, 0.750, 0.000) 逐步收拢到 (1.154, 1.091, 1.000),这就是"每个进程约获得 1/n"这个承诺在时间上的兑现过程。

粒度说明:上表按 1 个时间单位重算一次,是最容易手算的粒度;教材给的规则是"让选中的进程一直运行,直到它的比率超过最接近它的那个进程",粒度更粗、重算次数更少,但两者的选人依据(比率最小)完全一致。按题目给的粒度走即可。

二、公平分享调度算法

保证调度以进程为公平单位,但进程数是用户自己决定的:

系统中只有两个用户,用户 1 启动了 4 个进程 A、B、C、D,用户 2 只启动了 1 个进程 E。轮转调度让每个进程各轮一个时间片 ⇒ 每个进程拿到 1/5 ⇒ 用户 1 拿到 80%、用户 2 只拿到 20%

对进程而言这非常公平,对用户 2 就明显不公平。公平分享调度因此改按用户分配份额,再用下面这条生成规则把"用户份额"翻译成"进程序列":周期长 L=wu,每个周期里用户 uwu 个时间片,用户内部的各进程跨周期连续做 RR

RR公平分享调度
轮转的对象进程用户(用户内部再对进程 RR)
每一轮谁拿一片每个进程各一片每个用户按权重拿 wu
一个用户的总份额与他的进程数成正比与他的进程数无关
是否带权不带权带权

第三行正是这个算法存在的理由:只有"总份额与进程数无关",多开进程才占不到便宜。

三种权重下调度序列的逐周期生成(想自己推任意权重的序列时展开)

情形一:权重 1 : 1。 L=2,每周期用户 1 拿 1 片、用户 2 拿 1 片;用户 1 内部按 A→B→C→D 轮转:

周期1234
用户 1 的那一片ABCD
用户 2 的那一片EEEE
序列:A E B E C E D E A E B E C E D E

两个用户各占 50%,而用户 1 的四个进程每人只有 12.5%。

情形二:权重 2 : 1。 L=3,每周期用户 1 拿 2 片、用户 2 拿 1 片;用户 1 内部仍按 A→B→C→D 接着轮:

周期1234
用户 1 的两片A BC DA BC D
用户 2 的一片EEEE
序列:A B E C D E A B E C D E

用户 1 占 2/3 ≈ 67%,用户 2 占 1/3 ≈ 33%。

情形三:权重 3 : 1(教材未给,用规则自己推)。 L=4,每周期用户 1 拿 3 片、用户 2 拿 1 片,用户 1 内部继续接着轮:

周期1234
用户 1 的三片A B CD A BC D AB C D
用户 2 的一片EEEE
序列:A B C E D A B E C D A E B C D E

一个完整循环长 16 个时间片,用户 1 占 12/16 = 75%,用户 2 占 4/16 = 25%,正是 3 : 1。注意用户 1 的四个进程需要 4 个周期才轮完一圈——这是"用户份额固定、内部再分"的必然结果:进程越多,每个进程分到的越少。

有了这条规则,给定任意权重都能自己把序列写出来,不必去记教材上那两串字母。

三、两种算法对比

特性保证调度公平分享调度
公平单位进程用户
分配依据每个进程获得约 1/n 的 CPU 时间每个用户按权重获得 CPU 份额
判据(选谁)公平比率最小的进程当前周期里份额还没发完的用户,其内部下一个待轮进程
需要维护什么每个进程的已执行时间与创建时刻每个用户的权重、已用份额,以及用户内部的轮转指针
会不会饥饿不会——不被调度时比率自动下降,早晚成为最小不会——每个周期每个用户都有份额
多开进程有没有用有用(进程越多,该用户占的总份额越大)没用(用户总份额固定)
适用场景进程间公平多用户系统中用户间公平

考点速记

  1. 公平调度换的是承诺的东西:前面七种算法承诺次序,它承诺份额
  2. 保证调度为每个进程保证约 1/n 的处理机时间,靠公平比率 = 实际获得 ÷ 应当获得选人,每次挑比率最小的。比率 <1 表示系统亏欠它,>1 表示它已超额。
  3. ⚠️用比值而不用差值,是为了把欠账折算成相对于自身应得份额的比例——应得份额不同的进程之间,差值没法比。
  4. ⚠️它天然不饥饿、也不需要老化补丁:分母(应得时间)随时间单调增长,一个进程只要一直没跑,比率就会一直往下掉,早晚被选中。"老化"被内建进了比较键里。
  5. ⚠️对进程公平不等于对用户公平——进程数由用户自己决定,一个用户开 10 个进程就能拿走 10 份。
  6. 公平分享调度因此改按用户分配份额:周期长 L=wu,每周期用户 uwu 个时间片,用户内部跨周期连续 RR。本质是按用户加权的 RR。

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

公平调度至今不单独成题。 本页下方练习区渲染的是整个 cpu-scheduling-algorithm 标签下的 12 道题、由 8 篇算法共享,范围比本节宽,属正常

它在大纲的"CPU 调度算法"条目下,不能跳过,但投入按"读懂即可"来定。 它的价值主要有两处:

第一,第四条那个"不饥饿"的机制值得单独理解。 前面的算法防饥饿都要外挂老化补丁 (优先级调度、MLFQ 都是),而公平调度把老化内建进了比较键—— 分母随时间单调增长,欠账自然会被补上。这是一种和"打补丁"完全不同的解法。

第二,第五条那个"对进程公平 ≠ 对用户公平"是理解调度目标的一处分辨点。调度的基本概念里说"公平不等于平均", 这里给出了另一层:公平的对象是谁,本身就是一个要先定下来的问题

复习优先级读一遍即可,不必记公式。 记住"承诺份额而非次序""比率最小者先跑" "对进程公平不等于对用户公平"三句话就够。周期长 L 与序列生成规则至今没考过。

易错:认为公平调度也需要老化防饥饿。不需要——分母单调增长,老化已被内建进比较键。

易错:用差值而不是比值衡量欠账。应得份额不同的进程之间,差值没法比

易错:认为对每个进程公平就是对每个用户公平。进程数由用户自己决定,开得多就拿得多。

易错:把公平调度当成一种"更好的 RR"。它换的是优化目标——从承诺次序变成承诺份额。

教材出处
  • 汤小丹《计算机操作系统》3.3.6 基于公平原则的调度算法(保证调度的五个功能步骤与"调度比率最小的进程、让它一直运行到超过最接近它的进程比率为止";公平分享调度的 80%/20% 问题与 1:1、2:1 两条强制调度序列),印刷 p96–p97

相关知识

多级反馈队列调度多处理机调度调度的基本概念与目标优先级调度

真题练习