- 核心设计理念
基本目标
• 完全公平:按权重而非绝对时间分配CPU份额
• 低开销:调度决策高效,适合大规模任务
• 良好响应性:保证交互式任务及时响应
公平性定义
• 公平 = 每个任务获得与其权重成比例的CPU时间
• 高优先级任务(低nice值)获得更多CPU时间
• 防止任何任务饿死
- 核心机制:虚拟运行时(vruntime)
vruntime计算
vruntime_increase = 实际运行时间 × (NICE_0_LOAD / 任务权重)
• 普通优先级任务:vruntime ≈ 实际运行时间
• 高优先级任务:vruntime增长更慢
• 低优先级任务:vruntime增长更快
vruntime的意义
• 衡量任务"已消耗的公平份额"
• vruntime越小,表示"吃亏"越多,优先级越高
• 调度目标:让所有任务的vruntime尽可能同步
- 数据结构与调度算法
红黑树管理
• 键值:任务的vruntime
• 最左节点:vruntime最小的任务,下一个被调度
• 操作效率:插入、删除、查找均为O(logN)
调度过程
-
选择任务:从红黑树取最左节点(vruntime最小)
-
任务运行:在CPU上执行
-
时间统计:更新实际运行时间和vruntime
-
重新插入:任务放回红黑树(如果仍可运行)
-
选择下一个:重复步骤1
-
时间管理与调度周期
关键参数
• sched_latency_ns:目标调度周期(默认24ms)
• sched_min_granularity_ns:最小时间片(默认3ms)
动态时间片计算
时间片 = max(调度周期/N, 最小时间片)
• 任务少时:每个任务获得较长时间片
• 任务多时:保证所有任务都能在周期内运行
- 任务状态处理
新任务创建
• vruntime初始化为当前运行队列的min_vruntime
• 给予适当补偿,避免过度"插队"
睡眠任务唤醒
• 关键机制:vruntime补偿 = -sched_latency_ns/2
• 目的:提升交互式任务响应性,但不破坏公平性
• 补偿值固定:不随任务数变化,保证最小响应性
实时进程关系
• 调度类优先级:RT > CFS > Idle
• 实时进程:总是抢占普通CFS任务
• 独立队列:实时进程使用优先级数组,CFS使用红黑树
- 多核与负载均衡
CPU间迁移
• vruntime调整:新vruntime = 原vruntime - 源CPUmin_vruntime + 目标CPUmin_vruntime
• 保持公平:迁移后维持相对进度位置
• 防止蜂拥:迁移不会获得不公平优势
负载均衡触发
• 周期性检查(每1-10ms)
• 新任务创建
• 任务唤醒
• CPU空闲时
- 抢占机制
调度触发点
- 主动调度:系统调用、阻塞操作
- 时钟中断:周期性检查(tick机制)
- 实时抢占:高优先级实时任务就绪
- 唤醒抢占:睡眠任务唤醒时可能抢占
完全抢占支持
• CONFIG_PREEMPT:允许内核态抢占
• 关键区域保护:持有自旋锁时不可抢占
• 中断返回路径:实际调度发生点
- 实际表现特性
优点
• ✅ 真正公平:按权重精确分配CPU时间
• ✅ 高扩展性:红黑树支持大量任务高效调度
• ✅ 良好响应性:交互式任务获得优先处理
• ✅ 自适应:动态调整时间片,平衡延迟和吞吐量
可调参数
查看和调整调度参数
/proc/sys/kernel/sched_latency_ns
/proc/sys/kernel/sched_min_granularity_ns
/proc/sys/kernel/sched_migration_cost_ns
- 总结
CFS是Linux调度器的重大进步,通过vruntime机制实现了真正的公平性:
• 核心创新:用vruntime替代传统时间片
• 高效实现:红黑树保证调度决策高效
• 公平保证:权重机制确保按比例分配CPU
• 响应性保障:睡眠补偿和完全抢占机制
• 多核优化:负载均衡和vruntime迁移保持跨CPU公平
这种设计使Linux能够同时满足服务器的高吞吐量和桌面的交互性需求,是现代操作系统调度算法的典范。