Linux CFS(完全公平调度器)原理与实现细节全解析(1)

一、背景、动机与设计目标

CFS(Completely Fair Scheduler,完全公平调度器)是Linux内核自2.6.23版本起采用的默认进程调度器,用于替代之前的O(1)调度器。其引入的核心动机在于解决传统调度器在多任务交互场景下公平性不足、响应延迟偏高等问题。

在CFS之前,O(1)调度器虽然具有常数时间复杂度,适合大规模并发,但其基于固定时间片 + 多级优先级数组的设计难以实现真正的“公平”:

  • 高优先级任务可能长期抢占CPU;
  • 低优先级或交互式任务(如桌面应用)容易出现明显卡顿;
  • 调度行为对I/O密集型任务的友好度有限。

随着桌面和服务器负载对交互响应性、公平性、可扩展性的要求不断提高,社区迫切需要一种:

  • 能更合理分配CPU时间
  • 能体现任务优先级
  • 又能保持较好可扩展性与实现简洁性

的新调度机制。

CFS的设计目标正是围绕“完全公平”展开:

(1)摒弃传统时间片

不再为每个任务分配固定时间片,而是引入统一度量 —— 虚拟运行时间(vruntime)

(2)按vruntime选任务

调度器总是选择vruntime最小的可运行任务执行,使所有任务在长时间尺度上按权重成比例分享 CPU。

(3)结构简洁、易扩展

利用红黑树管理可运行任务;通过“调度类”(schedule class)机制,为实时调度、批处理调度等扩展预留空间。

(4)良好可扩展性

在任务数高达数千时,仍能保持可接受的调度开销。

二、核心概念与关键抽象

从宏观上看,CFS要解决的问题可以概括为三个核心问题:

(1)“完全公平”在CFS中的具体含义是什么?

(2)CFS如何定义、维护并使用虚拟运行时间(vruntime)来实现这种公平?

(3)CFS如何通过调度实体(sched_entity)+ 运行队列(cfs_rq)+ 红黑树

三者的配合完成实际调度决策?

本节先从整体抽象入手,再逐步深入实现细节。

2.1 “完全公平”的含义与实现近似

CFS所谓的“完全公平”,本质上是一种基于权重的比例公平(proportional fairness)

  • 若系统中有N个权重相同的可运行任务,则每个任务应获得约1/N的CPU时间;
  • 若任务权重不同(由nice值映射),则任务获得的CPU时间应与其权重成正比。

但是现实世界中有几个硬条件:

  • CPU是离散资源,只能一次运行一个任务;
  • 上下文切换存在开销;
  • 任务会频繁睡眠/唤醒、I/O 阻塞、迁移等。

所以CFS采取近似实现

(1)为每个可调度对象维护一个虚拟运行时间vruntime,表示该任务在“公平意义上已经消耗了多少CPU”;

(2)所有可运行任务按vruntime排序,放在一棵红黑树中;

(3)每次调度时,总是选择vruntime最小的任务运行;

(4)任务运行期间,其vruntime按如下公式增长:

[\Delta \text{vruntime} = \Delta t_\text{exec} \times \frac{\text{NICE_0_LOAD}}{\text{weight}} ]

vruntime = (runtime * weight * lw->inv_weight) >> WMULT_SHIFT

其中:

  • \Delta t_\text{exec}):实际运行的物理时间;

  • weight:任务权重,由nice值映射;

  • NICE_0_LOAD:nice=0对应的标准权重,一般为1024。

由此可见:

  • 权重越大(优先级越高,nice越小),vruntime增长越慢;
  • 权重越小(优先级越低,nice越大),vruntime增长越快。

长时间看,所有任务的vruntime会趋于“对齐”,从而实现按权重分配CPU时间的比例公平

如果没有vruntime这一层权重归一化,只按物理时间轮转,那么所有任务将几乎平均地分到CPU 时间,优先级语义基本丧失。

更多内容请看下回。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值