CPU 调度算法经典

共 20 题
📑 题目列表 20 题
#
★★★

1. FCFS、SJF/SRTF、时间片轮转(RR)、优先级调度、多级反馈队列五类调度算法的原理与优缺点对比?

FCFS、SJF/SRTF、时间片轮转(RR)、优先级调度、多级反馈队列五类调度算法的原理与优缺点是什么?

  • FCFS:按到达顺序,简单但平均等待时间大,有护航效应。
  • SJF/SRTF:选最短作业/剩余时间最短,最优平均周转但需预知运行时间,SJF 非抢占可能饥饿。
  • RR:时间片轮转,公平响应,但时间片影响吞吐。

FCFS(先来先服务)按到达顺序调度,实现简单、无饥饿,但短作业被长作业阻塞(护航效应),平均等待时间可能很大。SJF(短作业优先)选择运行时间最短的进程,能最小化平均周转时间,但需预知运行时间,且非抢占 SJF 可能让长作业饥饿;SRTF(最短剩余时间优先)是 SJF 的抢占版本,动态选择剩余时间最短者,平均周转最优但切换频繁。时间片轮转(RR)按到达顺序排队,每进程运行一个时间片后轮转,响应时间好、公平,但时间片过小切换开销大、过大退化为 FCFS。优先级调度按优先级选择,高优先级任务响应快,适合实时场景,但低优先级可能饥饿(需老化)。多级反馈队列(MLFQ)设置多个不同优先级的队列,新进程进入最高优先级,时间片用完降级,交互/短任务可在高队列快速完成,长任务不断降级,兼顾响应时间与吞吐,且通过老化防饥饿,是现代操作系统(如 Linux CFS 之前)广泛采用的调度思想。

五类算法在"响应时间、周转时间、公平性、实现复杂度"上各有取舍。SJF/SRTF 是最优平均周转但理想化;RR 保证响应但牺牲吞吐;MLFQ 是综合折中。掌握"目标优化指标"与"算法代价"的对应关系是解答对比题的关键。

#
★★★

2. 多级反馈队列(MLFQ)为什么被认为兼顾了响应时间与周转时间?其防饥饿机制(优先级提升)如何设计?

多级反馈队列(MLFQ)为什么能兼顾响应时间与周转时间?其防饥饿机制如何设计?

  • 响应时间:交互/短任务在高优先级队列快速切换,响应快。
  • 周转时间:长任务在低队列批处理,不阻塞短任务。
  • 防饥饿:周期性把所有进程提升到最高优先级队列(老化/优先级提升)。

MLFQ 设置多级优先级队列,级别越高时间片越短。新进程进入最高优先级队列,在该队列中运行完时间片仍未完成则降级到下一级,以此类推;在上层队列中进程被抢占(时间片耗尽)才降级。这样交互/短任务在高优先级队列几乎立即被调度,响应时间好;而长任务逐渐降级到低队列,由低队列较长的时间片批量执行,不打断短任务,周转时间也较好。因此 MLFQ 不需要预先知道运行时间,就能自动区分"短/交互任务"与"长任务",兼顾响应与周转。防饥饿机制是周期性提升(老化):每隔一段时间,把所有进程提升到最高优先级队列,保证低队列中的长任务最终也能被调度,避免被源源不断的新任务"饿死";同时配合时间片与计数器判断进程是否由 IO 密集(交互)转为 CPU 密集,动态调整优先级。

MLFQ 的精髓是"用时间片开销模式自动学习进程类型",无需先验知识。它用"多级队列 + 时间片递减 + 老化提升"同时解决响应(高队列抢占)、周转(低队列批处理)与饥饿(老化)。理解"为什么能兼顾"要从队列数量与时间片设计入手。

#
★★★

3. CFS 的虚拟运行时间(vruntime)与红黑树调度,新进程/睡眠进程的惩罚与补偿?

CFS 的虚拟运行时间(vruntime)与红黑树调度如何工作?新进程与睡眠进程的惩罚与补偿如何处理?

  • CFS 用 vruntime 记录虚拟运行时间,按 vruntime 最小的进程优先调度。
  • vruntime 按权重折算,实现公平。红黑树按 vruntime 排序,O(log n) 选择最小者。
  • 新进程 vruntime 设为当前最小值,避免新进程抢占;睡眠进程 vruntime 补偿,避免睡眠后被惩罚。

CFS(完全公平调度器)为每个进程维护虚拟运行时间 vruntime,其递增速率与权重成反比(权重高的进程 vruntime 增长慢),每次调度选择 vruntime 最小的进程运行,从而保证公平。实现上用红黑树按 vruntime 排序就绪进程,取最左节点(最小 vruntime)作为下一个运行进程,插入/删除复杂度 O(log n),适合大量进程。对新进程,CFS 将其 vruntime 初始化为当前树中最小 vruntime(或取当前运行进程的 vruntime),避免新进程因 vruntime 为 0 而长期霸占 CPU。对睡眠进程,当它唤醒时若其 vruntime 远小于当前最小值,说明它因睡眠"落下"了,CFS 会将其 vruntime 补偿(上调)到不至于太靠前的位置,避免睡眠优先抢占;同时为了保证交互性,唤醒的进程通常会被放回队列靠前位置,减少调度延迟。新进程与睡眠进程的"惩罚/补偿"本质是平衡"公平性"与"交互体验"。

CFS 的核心思想是"用虚拟时间替代优先级计数,实现按权重公平"。vruntime 最小者先运行,权重通过 vruntime 增长速率体现。新进程与睡眠进程的处理是为了避免"年幼者霸占"与"睡眠者被冷落",是 CFS 细节考点。

#
★★★

4. EDF 为何是最优单处理器实时调度,可调度性判定 U ≤ 1 与 RM 的 U ≤ n(2^(1/n)-1) 如何对比?

为什么 EDF 是最优单处理器实时调度?其可调度性判定 U ≤ 1 与 RM 的 U ≤ n(2^(1/n)-1) 有何对比?

  • EDF(最早截止时间优先)动态调度,优先截止时间最近者。
  • EDF 最优性:若任何算法能调度,则 EDF 也能,可调度判定为总利用率 U ≤ 1。
  • RM(速率单调)静态优先级,可调度判定 U ≤ n(2^(1/n)-1),随 n 增大趋于 ln2≈0.693。

EDF(Earliest Deadline First)是动态优先级调度,每次选择截止时间最近的作业执行,在单处理器上对于抢占式周期性任务是最优的:只要系统总利用率 U ≤ 1(即所有任务负载之和不超过处理器容量),EDF 就能保证所有任务在截止时间内完成;若 U > 1,则任何算法都无法调度。RM(Rate Monotonic)是静态优先级调度,周期越短、优先级越高,可调度性判定为 U ≤ n(2^(1/n)-1),其中 n 为任务数,当 n 趋于无穷时该上界收敛到 ln2 ≈ 0.693。对比:EDF 的利用率上界为 100%(更宽松),调度更灵活,但实现复杂(需动态维护截止时间、可能抢占频繁);RM 上界固定(约 69.3%),实现简单、开销低,适合任务数固定且周期已知的场合。因此 EDF 在"最优性"与"利用率"上胜出,RM 在"简单性"上胜出。

区分 EDF 与 RM 的关键:EDF 动态、最优、利用率 100%;RM 静态、上界 69.3%。可调度判定公式是硬考点,需记住 RM 的 n(2^(1/n)-1) 随 n 衰减到 ln2,EDF 的充分必要条件为 U ≤ 1。该题常结合"是否能满足实时性"的计算题。

#
★★★

5. 优先级反转问题,为什么实时任务可能被低优先级任务阻塞,优先级继承与优先级置顶如何解决?

什么是优先级反转?为什么实时任务可能被低优先级任务阻塞?优先级继承与优先级置顶如何解决?

  • 优先级反转:高优先级任务被低优先级任务长期阻塞,因低优先级任务持有共享资源且被中优先级任务抢占。
  • 优先级继承:低优先级任务临时继承高优先级任务的优先级,避免被中优先级抢占。
  • 优先级置顶:持有资源的任务优先级临时提升到资源最高优先级。

优先级反转是指高优先级任务因等待低优先级任务释放资源而长期无法执行,且可能被中等优先级任务进一步拖延。典型场景:任务 L(低优先级)持有共享资源,任务 H(高优先级)需要该资源而阻塞;此时任务 M(中优先级)到达,抢占 L 执行,使持锁的 L 无法运行,H 被 L 和 M 双重阻塞,形成"反转"。解决手段:优先级继承(priority inheritance)——当低优先级任务 L 持有高优先级任务 H 所需的资源时,L 临时继承 H 的优先级,使 L 能优先于 M 运行并尽快释放资源,H 恢复后 L 再降回原优先级;优先级置顶(priority ceiling)——事先规定每个资源有一个"最高可能优先级",任何持有该资源的任务优先级都被临时提升到该上限,从而避免被中间优先级任务抢占。两者都保证"持锁任务不会被无关任务抢占",从而缩短反转时间。

优先级反转的本质是"持锁任务被抢导致持锁方无法释放"。优先级继承是"动态提升持锁者优先级",优先级置顶是"静态设定资源上限",两者都解决"持锁者被抢占"。答案核心是"高优先级任务被低优先级间接阻塞,且中间优先级加剧"。

#
★★

6. 时间片长度的选取权衡,过长退化为 FCFS、过短切换开销放大,如何折中?

时间片长度的选取如何权衡?过长过短各有什么弊端,如何折中?

  • 时间片过长:退化为 FCFS,响应时间差。
  • 时间片过短:上下文切换开销占比大,吞吐下降。
  • 折中:兼顾响应与切换开销,通常数十毫秒级。

时间片(time quantum)是 RR 与 MLFQ 的关键参数。若时间片过长,进程在片内基本能完成,调度退化为 FCFS,交互进程响应时间差,短任务被长任务拖累;若时间片过短,切换开销(保存/恢复上下文、TLB/缓存失效)占比增大,CPU 有效吞吐下降。折中原则是让时间片"大于一次上下切换开销的若干倍"(如切换需 1ms,时间片取 10~100ms),使切换开销占比可接受,同时保证交互进程能在合理时间内得到响应。现代 OS 常采用自适应或分层设计:高优先级队列时间片短(保证交互响应),低优先级队列时间片长(利于长任务吞吐),这就是 MLFQ 的设计思想。时间片也可依据进程类型/负载动态调整。

时间片是"响应时间"与"吞吐"的权衡杠杆。核心是让切换开销占比小、响应延迟可接受。回答"过高退化为 FCFS、过低放大切换开销,折中取切换开销的数十倍"即可,再补充 MLFQ 的分层时间片思想。

#
★★

7. 周转时间、带权周转时间、响应时间、等待时间四个调度指标的计算与适用场景?请用一组进程实例演算。

周转时间、带权周转时间、响应时间、等待时间四个指标如何计算?各适用什么场景?请用一组进程实例演算?

  • 周转时间 = 完成时间 - 到达时间;带权周转时间 = 周转时间 / 服务时间。
  • 响应时间 = 首次响应 - 到达时间;等待时间 = 周转时间 - 服务时间。
  • 适用场景:周转时间反映吞吐/整体效率,响应时间反映交互体验,等待时间反映公平性。

指标定义:周转时间(T)=完成时间-到达时间,反映进程从提交到完成的总耗时;带权周转时间=T/服务时间,反映单位服务时间被拖长的程度,其值越小越好、最小为 1;响应时间=首次获得 CPU 的时间-到达时间,反映交互体验;等待时间=周转时间-服务时间(即进程在就绪队列中等待的总时间),反映公平性。适用场景:批处理系统看重周转时间(衡量吞吐),交互系统看重响应时间,公平性分析看等待时间。举例:进程 A(服务 2)、B(服务 3)、C(服务 5),均 0 时刻到达,按 FCFS 顺序 A→B→C:A 完成 2、B 完成 5、C 完成 10;周转时间分别为 2、5、10,平均 17/3≈5.67;带权周转分别为 2/2=1、5/3≈1.67、10/5=2,平均 4.67/3≈1.56;等待时间分别为 0、2、5。若改按 SJF(A→B→C 相同),指标一致;若用 RR 时间片 1,则响应时间分别为 0、1、2,等待时间变化。

四个指标是调度算法的评价基准,计算关键在于"完成时间、到达时间、服务时间"三个原始量。带权周转时间能消除"服务时间长短"的影响,更公平地比较不同调度。实例演算需先确定调度顺序,再逐项推导完成时间。

#
★★

8. 抢占式/非抢占式、时间片轮转、多级反馈队列(MLFQ)在真实 OS 中的体现?

抢占式/非抢占式、时间片轮转、多级反馈队列(MLFQ)在真实 OS 中如何体现?

  • 抢占式:时钟中断触发时间片到期,强制切换。
  • 非抢占式:进程主动让出或阻塞才切换。
  • RR 与 MLFQ 都是抢占式调度,现代 OS 以抢占式为主。

真实 OS 普遍采用抢占式调度,通过时钟中断在时间片到期或更高优先级进程就绪时强制切换,保证响应与公平;非抢占式只在进程主动让出 CPU(如阻塞 IO)或退出时切换,多用于简单系统或特定低层调度。RR 是抢占式轮转的体现,现代交互系统(如桌面、实时)用时间片轮转保证响应。MLFQ 的思想在真实 OS 中体现为多优先级队列:Windows 用多级优先级队列并按优先级升降级;Linux 早期调度器(O(1))也用多级队列,现代 CFS 摒弃固定队列改用红黑树按 vruntime 公平抢占,但保留"新进程优先、交互进程优待"的 MLFQ 精神。实时调度(SCHED_FIFO/RR)在 Linux 中也是抢占式。总之,抢占式 + 时间片 + 多级反馈是主流交互式 OS 的调度骨架,MLFQ 是其理论母版。

该题把经典算法映射到真实系统。核心是"抢占式"是常态(靠时钟中断),"时间片"是轮转基础,"MLFQ"是优先级队列的原型,而 CFS 用红黑树 + vruntime 实现了更优雅的公平调度。回答时说明"经典算法→真实实现"的对应。

#
★★

9. 实时调度(SCHED_FIFO/RR/DEADLINE)与普通调度的优先级映射与风险(饥饿/锁死)?

实时调度(SCHED_FIFO/RR/DEADLINE)与普通调度的优先级如何映射?有何风险?

  • Linux 实时调度类 SCHED_FIFO、SCHED_RR、SCHED_DEADLINE。
  • 实时优先级高于普通(nice)优先级,实时任务优先运行。
  • 风险:实时任务可能饥饿普通任务;实时任务持锁被阻塞或无期限运行导致系统卡死。

Linux 中实时调度类(SCHED_FIFO、SCHED_RR、SCHED_DEADLINE)的优先级高于普通调度类(SCHED_OTHER/CFS)。SCHED_FIFO 是先进先出、无时间片,实时任务运行直到主动让出或阻塞;SCHED_RR 在实时任务间按时间片轮转;SCHED_DEADLINE 基于 EDF,为任务指定参数(运行时间/周期/截止时间)精确保证实时性。实时优先级(1~99)整体高于普通 nice 优先级,因此只要有实时任务就绪,普通任务就被抢占。风险:一是饥饿——若实时任务持续运行(如 SCHED_FIFO 中无阻塞的忙循环),会饿死普通任务甚至系统;二是锁死——实时任务持锁后若被更高优先级抢占或自身阻塞,可能长时间持锁导致依赖该锁的其他任务阻塞,甚至系统无响应;三是优先级反转与死锁。因此配置实时任务需谨慎,避免无界忙循环,处理锁与阻塞,必要时用 CPU 隔离与亲和性。

实时调度关键是"优先级高于普通,抢占式保证硬实时",但"高优先级 + 抢占"也带来饥饿与锁死风险。回答要平衡"实时性保证"与"可能饿死系统/持锁卡死"两面,体现出对生产环境的理解。

#
★★

10. 调度算法对比,FCFS/SJF/RR/多级反馈队列如何选择?

FCFS、SJF、RR 与多级反馈队列如何对比?

  • FCFS:简单、无饥饿、平均等待大。
  • SJF:最小平均周转、需预知时间、长作业可能饥饿。
  • RR:公平响应、时间片权衡。

FCFS 实现最简单、无饥饿,但平均等待时间大,存在护航效应(短作业被长作业阻塞)。SJF 使平均周转时间最小,但需预知运行时间(现实中不可得),且长作业可能饥饿,非抢占 SJF 尤其明显。RR 通过时间片轮转保证公平与响应,但时间片大小影响吞吐,且不区分任务类型。MLFQ 综合前两者:新进程进高优先级队列保证响应,时间片用完降级让长任务在低队列批处理,兼顾周转,且无需预知运行时间,通过老化防饥饿。因此 MLFQ 是"兼顾响应与吞吐、自动适应任务类型"的综合性调度,是实践中最被认可的设计;FCFS/SJF 偏理论或特定场景,RR 偏交互但无区分度。

对比的主线是"是否需预知时间、是否公平、是否兼顾响应与周转"。MLFQ 的优胜在于"无需预知时间 + 自动分类 + 兼顾两指标",这是它成为现代调度母版的原因。回答时按"指标-算法优劣"逐项比较。

#
★★

11. 多级反馈队列(MLFQ),优先级老化与时间片如何设计?

多级反馈队列中优先级老化与时间片如何设计?

  • 老化:定期把所有进程提升到最高优先级,防饥饿。
  • 时间片:高队列时间片短、低队列时间片长,区分交互与长任务。
  • 降级:时间片用完未完成则降级。

MLFQ 中,时间片的设计是"队列级别越高,时间片越短":高优先级队列时间片短,交互/短任务在其中快速完成或频繁让出,响应快;低优先级队列时间片长,长任务能在较大时间片内批量执行,减少切换。降级规则:进程在所在队列时间片用尽仍未完成,则下降到下一级队列;若进程因 IO 主动让出(尚未用完时间片),通常保持或提升优先级,以识别交互进程。优先级老化(aging)是防饥饿机制:周期性地把所有进程提升到最高优先级队列,保证长时间停留在低队列的进程最终也能被调度,避免被新进程持续抢占而饿死。时间片与老化配合,使 MLFQ 既保证短/交互任务响应,又保证长任务不被饿死。

时间片"从上到下递增"与老化"定期提升"是 MLFQ 的两个设计要点:前者区分任务类型,后者保证公平。理解"时间片用尽降级 + IO 主动让出升级 + 周期性老化"即可完整回答。

#
★★

12. Linux nice 值(-20 到 19)如何映射为 CFS 权重,为什么 nice 差 1 不等于固定百分比?

Linux nice 值(-20 到 19)如何映射为 CFS 权重?为什么 nice 差 1 不等于固定百分比?

  • nice 值范围 -20~19,越小优先级越高,映射为 CFS weight。
  • 权重映射近似:nice 每差 1,weight 约差距 1.25 倍(实际是近似)。
  • 因为权重是相对比例,实际获得的 CPU 比例取决于其他进程的总权重,故 nice 差 1 不代表固定百分比。

Linux 的 nice 值从 -20 到 19,值越小优先级越高(默认 0)。CFS 将 nice 值映射为权重(weight),通过一张静态表(sched_prio_to_weight)实现:nice 每增加 1,权重约乘 1.25(近似),nice 降低 1 权重约增大 1.25 倍。进程实际获得的 CPU 比例 = 自身权重 / 所有就绪进程权重之和。因此 nice 差 1 并不等于固定百分比:两个进程 nice 差 1 时,一个约得 1.25/(1+1.25)≈55.6%、另一个 44.4%,差约 11%;但若进程数更多或权重相差更大,比例会变化。CFS 用 vruntime 与权重结合实现"按权重比例公平",nice 值只影响相对权重,不直接对应固定 CPU 百分比,这解释了为什么"nice 差 1 不等于固定百分比"。

关键点是"nice 映射为权重,权重是相对值,CPU 比例取决于权重之比而非 nice 差本身"。nice 差 1 约 1.25 倍权重是记忆点,但实际比例随总权重变化。回答强调"相对比例 + 权重和"即可。

#
★★

13. CFS 的调度周期与最小粒度,sched_min_granularity 与 sched_latency 如何影响交互性与吞吐?

CFS 的调度周期与最小粒度如何设计?sched_min_granularity 与 sched_latency 如何影响交互性与吞吐?

  • sched_latency:调度目标周期,即"所有就绪进程在目标周期内都运行一次"。
  • sched_min_granularity:最小运行粒度,防止频繁切换。
  • 进程数多时实际周期被拉长,以平衡切换开销。

CFS 用 sched_latency(调度延迟目标)定义"理想情况下所有就绪进程在 sched_latency 内各运行一次"的时间窗口,其默认约 6ms 左右;sched_min_granularity 定义每个进程至少运行的最小时间片(默认约 0.75ms),防止进程切换过于频繁。调度周期(实际目标周期)按下式计算:target_period = max(sched_latency, nr_running * sched_min_granularity)。当就绪进程数超过 sched_latency/sched_min_granularity 时,目标周期被拉长到 nr_running * sched_min_granularity,以保证每个进程至少运行一个最小粒度。sched_latency 越小,目标周期越短,进程轮流更频繁,交互响应越好,但切换开销增大、吞吐下降;sched_min_granularity 越小,切换越频繁、交互越好但吞吐下降;反之周期长、粒度大则吞吐高但交互响应差。因此二者是"交互性"与"吞吐"的权衡旋钮。

理解"目标周期 = max(sched_latency, 进程数×最小粒度)"是核心。sched_latency 面向"交互延迟",sched_min_granularity 面向"切换开销下限",两者共同决定调度周期。回答时说明"进程数多时周期拉长"即可。

#
★★

14. 抢占式与非抢占式调度的差异及各自典型算法?

抢占式与非抢占式调度有何差异?各自有哪些典型算法?

  • 抢占式:可中断当前进程,时效性强,有切换开销。
  • 非抢占式:进程运行到主动让出或退出,实现简单。
  • 典型算法:非抢占有 FCFS、SJF;抢占有 SRTF、RR、优先级抢占、MLFQ。

非抢占式调度下,一旦进程获得 CPU 就运行到其主动让出(阻塞/退出)或被调度器强制结束,运行期间不会被中断,实现简单、切换开销小,但交互与实时性差,典型算法有 FCFS、非抢占 SJF。抢占式调度下,当更高优先级进程就绪或当前进程时间片到期时,调度器可强制中断当前进程,保证响应与公平,但需额外切换开销与同步处理,典型算法有 SRTF(最短剩余时间优先)、时间片轮转(RR)、优先级抢占、多级反馈队列(MLFQ)。现代操作系统几乎都采用抢占式调度(配合时钟中断),以保证交互响应与实时性;非抢占式多用于简单嵌入式系统或作为抢占式调度的底层补充。

差异核心是"能否在运行中强制切换"。抢占式用"时钟中断 + 优先级比较"保证响应,非抢占式靠"进程主动让出"。回答时列举典型算法并说明"现代 OS 以抢占式为主"即可。

#
★★

15. 调度的公平性,CFS 的虚拟运行时间与权重如何计算?

CFS 如何用虚拟运行时间与权重实现调度公平性?

  • vruntime 记录虚拟运行时间,与权重成反比增长。
  • 调度选择 vruntime 最小者,按权重比例分配 CPU。
  • 权重来自 nice 值,实现"按权重公平"。

CFS 的公平性基于"虚拟运行时间(vruntime)"。每个进程的 vruntime 以其实际运行时间按权重折算:vruntime 增长速率 = 实际运行时间 × (nice0 权重 / 自身权重),即权重高的进程 vruntime 增长慢,权重低的增长快。调度器每次选择 vruntime 最小的就绪进程运行,这样各进程的 vruntime 趋于相等,等于按权重比例公平分配 CPU:权重高的进程实际获得更多 CPU 时间,但 vruntime 保持一致。权重由 nice 值映射得到(-20~19 对应权重表),nice 越小权重越大。因此 CFS 实现了"按权重成比例、但虚拟时间趋于公平"的调度,既保证公平又允许通过 nice 调整优先级。红黑树按 vruntime 组织就绪队列,保证 O(log n) 选择最小 vruntime 进程。

公平性的核心是"用 vruntime 统一度量,权重决定增长速率"。因为 vruntime 相同才算公平,而权重高的进程"消耗同样的 CPU 时间但 vruntime 增长慢",所以获得更多 CPU。这是"按权重公平"的精髓。

#
★★

16. Linux EEVDF 调度器,EEVDF 如何取代 CFS,其虚拟时间与延迟目标(sched_latency)的设计动机如何?

Linux EEVDF 调度器如何取代 CFS?其虚拟时间与延迟目标的设计动机是什么?

  • EEVDF(最早虚拟截止时间优先)在 Linux 6.6 引入取代 CFS。
  • 为每个进程维护 eligible(最早)与 deadline 虚拟时间,选择 deadline 最早者。
  • 动机:解决 CFS 在周期/延迟目标上的问题,提供更精确的延迟控制与公平。

Linux 6.6 引入 EEVDF(Earliest Eligible Virtual Deadline First)调度器取代 CFS。EEVDF 在 CFS 的按权重公平基础上,为每个就绪进程维护"虚拟时间"与"虚拟截止时间":每个进程有一个虚拟截止时间(virtual deadline),等于其"虚拟开始时间 + 平均虚拟运行片段(sched_latency 相关的虚拟时间量)";调度器选择"deferred 且虚拟截止时间最早"的进程运行。相比 CFS 单纯选 vruntime 最小者,EEVDF 用"最早截止时间优先"更精确地控制每个进程的调度延迟,使各进程的调度间隔更均衡。设计动机:CFS 的周期/延迟目标(sched_latency、sched_min_granularity)在进程数多时只能保证"整体公平",无法精确控制每个进程的延迟上界;EEVDF 通过虚拟截止时间把"每个进程应在何时被调度"显式化,提供更细粒度、更可预测的延迟保证,同时保持按权重公平,并改善交互性与真实负载下的调度表现。

EEVDF 是 CFS 的演进,核心是"用虚拟截止时间替代简单最小 vruntime 选择",把延迟目标落实到每个进程的显式 deadline。理解"动机是更精确的延迟控制"与"虚拟时间 + 截止时间"的机制即可。

#
★★

17. 组调度(cgroup CPU),如何用 cpu.shares/cpu.max 对容器进行 CPU 分配与带宽限制,与 CFS 权重的关系如何?

cgroup CPU 组调度如何工作?cpu.shares 与 cpu.max 如何分配 CPU 与限制带宽?与 CFS 权重有何关系?

  • cpu.shares:相对权重,按组内权重比例分配 CPU。
  • cpu.max:上限(quota/period),限制组最多使用多少 CPU 带宽。
  • 与 CFS 权重:cpu.shares 映射到 CFS 权重,共享 CPU 时按比例分配。

cgroup 的 CPU 控制器提供两种机制。cpu.shares 是相对权重:当多个 cgroup 竞争 CPU 时,按各组的 shares 值比例分配 CPU 时间(例如组 A shares=100、组 B=200,则 A 得 1/3、B 得 2/3),它只影响"竞争时"的相对分配,不限制单组可达的最大 CPU。cpu.max 是带宽上限:格式为 quota/period(如 100000/100000 表示 1 个 CPU 的 100%),把组对 CPU 的使用限制在 quota/period 内,即使有空闲 CPU 也不超过,用于限流与计费。与 CFS 权重的关系:cpu.shares 直接映射到 CFS 的权重(weight),CFS 在共享 CPU 时按权重分配,因此 cgroup 层级的 shares 就是 CFS 权重在分组维度的体现;cpu.max 则是额外的硬性上限,与 CFS 权重正交——权重决定"如何分",max 决定"最多多少"。Docker/容器平台用二者实现 CPU 预留与配额。

关键是区分"相对分配(shares/权重)"与"硬性上限(max/quota)"。shares 是柔性比例,max 是刚性上限。cgroup 的 shares 与 CFS 权重是同一机制的层级化表达,理解"权重管比例、quota 管上限"即可。

#
★★

18. 处理器亲和性,sched_setaffinity 如何提升缓存命中与降低迁移开销,何时不该设置亲和性?

处理器亲和性(sched_setaffinity)如何提升缓存命中与降低迁移开销?何时不该设置亲和性?

  • sched_setaffinity 把线程绑定到特定 CPU 集合,减少迁移。
  • 好处:缓存/TLB 命中率提升,减少迁移开销。
  • 不应设置:负载不均时、任务数远多于核数、需要动态负载均衡的场合。

处理器亲和性(affinity)通过 sched_setaffinity 把线程/进程绑定到指定的 CPU 集合,使调度器尽量在其上运行,主要好处是:减少线程在核间迁移,避免迁移后 TLB/L1 缓存失效,提升缓存命中率;降低迁移开销;对 NUMA 环境可绑定到本地 NUMA 节点,减少跨节点访问延迟。因此对 CPU 密集、缓存敏感的任务(如网络转发、高频计算)设置亲和性收益显著。何时不该设置亲和性:当任务数远多于可用核数、或负载随时间动态变化时,绑定会让某些核忙碌而其他核空闲,妨碍负载均衡,反而降低整体吞吐;对 IO 密集、短任务、或以吞吐为主且核间迁移成本不高的场景,也应交给调度器动态均衡。因此应在"减少迁移开销"与"允许负载均衡"之间权衡,必要时用"软亲和性"(引导性提示)而非硬绑定。

亲和性是"用缓存局部性换调度灵活性"。回答要两方面:设置的好处(缓存/TLB、减少迁移、NUMA 本地)与不设的场合(负载不均、任务数多、需动态均衡)。核心是"绑定 vs 均衡"的权衡。

#
★★

19. 调度切换开销的构成,上下文切换的寄存器保存/缓存失效/TLB 失效,如何评估与优化切换频率?

调度切换开销由哪些构成?如何评估与优化切换频率?

  • 开销构成:寄存器保存/恢复、缓存失效、TLB 失效、内核栈切换。
  • 评估:perf、context-switch 计数、cache-miss、切换耗时。
  • 优化:减少切换频率、增大时间片、亲和性、协程、批量处理。

调度切换(上下文切换)的开销包括:CPU 寄存器与程序计数器、状态字的保存与恢复;跨进程切换时页表切换导致 TLB 全部失效、后续访问走慢路径;缓存(L1/L2)因地址空间变化而失效,重新加载开销大;内核栈切换与调度器运行开销。评估方法:用 perf 的 context-switches 或 schedule 事件统计切换次数与耗时;用 /proc/stat 的 ctxt 字段观测切换速率;用 pmu 的 cache-miss 指标量化缓存失效;用 vmstat/pidstat 观察切换频率。优化切换频率的手段:合理控制线程数避免过度并发;适当增大时间片(sched_min_granularity)减少强制切换;用 CPU 亲和性减少迁移与缓存失效;用协程/用户态调度替代频繁内核切换;对 IO 密集场景做批量唤醒与批量处理;减少锁竞争与唤醒抖动。

切换开销的本质是"硬件状态复用失败",缓存与 TLB 失效占比最大。评估靠"切换次数 + 缓存失效"综合,优化聚焦"减少切换次数 + 提升缓存复用(亲和性/协程)"。

#

20. 负载均衡与迁移,wakeup 迁移、周期负载均衡与 NUMA 感知如何配合?

处理器负载均衡与线程迁移如何工作?wakeup 迁移、周期负载均衡与 NUMA 感知各是什么?

  • wakeup 迁移:被唤醒的线程优先调度到空闲/负载低且共享缓存的 CPU。
  • 周期负载均衡:调度器周期性检查各 CPU 负载,迁移任务平衡。
  • NUMA 感知:优先把任务与内存放到同一节点,减少跨节点访问。

负载均衡(load balancing)指调度器把任务分布到各 CPU 以平衡负载。wakeup 迁移:当线程被唤醒时,调度器优先选择"空闲或负载较低、且与唤醒者共享缓存(同一 SMT 核/同核)"的 CPU 运行,兼顾唤醒延迟与缓存局部性。周期负载均衡:调度器周期性(如每 tick 或 idle 时)比较各 CPU 的运行队列负载,把负载高的 CPU 上的任务迁移到空闲/低负载 CPU,维持整体平衡。NUMA 感知:在 NUMA 架构下,访问本地内存远快于远端内存,调度器在迁移任务时尽量保持任务与已分配内存在同一 NUMA 节点(若任务迁移到远端,则触发内存迁移或访问变慢),并优先把任务放到内存所在节点。三者综合:wakeup 迁移优化"唤醒延迟",周期均衡优化"整体负载",NUMA 感知优化"内存访问延迟",共同构成现代调度器的迁移决策。

迁移是"负载均衡"与"缓存/NUMA 局部性"的权衡。wakeup 迁移、周期均衡、NUMA 感知分别针对"响应、整体负载、内存亲和"。回答时说明三者目标与权衡即可。