Linux内核CFS完全公平调度器深度实战
1. CFS核心理念
完全公平调度器(Completely Fair Scheduler)自Linux 2.6.23版本起成为默认的普通进程调度器。与O(1)调度器使用时间片不同,CFS的核心思想是:不分配固定时间片,而是让每个进程公平分享CPU时间。
CFS的目标很简单:让所有可运行进程获得完全相等的CPU时间。在理想的多任务系统中,N个进程应各自获得1/N的CPU时间。现实中由于进程休眠、I/O等待等原因,实际实现需要对vruntime进行精细管理。
CFS引入了一个关键概念——虚拟运行时间(vruntime),它度量每个进程已经在CPU上运行了多少"加权"时间。vruntime最小的下一个获得CPU,保证公平性。
2. 红黑树数据结构
CFS使用红黑树(Red-Black Tree)作为可运行进程队列,O(log n)查找效率。红黑树的键值为进程的vruntime。内核数据结构:
struct cfs_rq {
struct load_weight load;
unsigned long runnable_weight;
unsigned int nr_running;
u64 min_vruntime;
struct rb_root_cached tasks_timeline;
struct sched_entity *curr, *next, *last, *skip;
};
3. vruntime计算与权重体系
vruntime核心公式:vruntime += delta_exec * (NICE_0_LOAD / weight)
nice值越高权重越小,vruntime增长越快,越早被抢占。nice值之间CPU份额按1.25倍等比换算。
| nice值 | 权重 | 相对CPU比例 |
|---|---|---|
| -20 | 88761 | 最高优先级 |
| 0 | 1024 | 基准值 |
| 10 | 110 | 约为基准的1/9 |
| 19 | 15 | 最低优先级 |
4. 调度延迟与粒度控制
- sched_latency_ns(默认6ms):调度周期
- min_granularity_ns(默认0.755ms):最小时间片
- wakeup_granularity_ns(默认1ms):唤醒抢占粒度
时间片 = sched_latency / nr_running(不低于min_granularity)。
5. 调度策略体系
- SCHED_NORMAL:普通分时进程
- SCHED_BATCH:批处理进程
- SCHED_IDLE:极低优先级
- SCHED_FIFO/SCHED_RR:实时策略
- SCHED_DEADLINE:EDF最早截止时间优先
调度类优先级:dl_sched_class → rt_sched_class → fair_sched_class → idle_sched_class
6. SMP负载均衡
CFS通过sched domain层级结构实现多核负载均衡:调度域分组CPU覆盖NUMA节点/Die/Package等粒度,负载均衡时机包括IDLE(空闲拉取)、BALANCE_FORK、BALANCE_WAKE。AutoNUMA Balancing自动将进程迁移至内存所在节点。
7. 内核抢占与上下文切换
- 用户态抢占:返回用户态时检查TIF_NEED_RESCHED
- 内核态抢占(CONFIG_PREEMPT):安全切入点允许抢占
- Voluntary Preemption:cond_resched()主动让出
- Full Preemption(CONFIG_PREEMPT_RT):中断线程化
核心流程:schedule() → pick_next_task() → context_switch(switch_mm + switch_to)
8. 组调度与cgroup CPU控制器
- cpu.weight:组间份额(默认100,1-10000)
- cpu.max:带宽限制"50000 100000"
- cpu.max.burst:短时爆发量
- cpu.pressure:PSI压力指标
- CFS Bandwidth Control:严格配额限制
9. NUMA感知调度
NUMA Balancing自动将进程迁移到内存所在节点。工具:numactl绑定策略,numastat查看统计,/proc/zoneinfo查看节点状态。
10. 调试与调优工具
/proc/sched_debug:每CPU详细调度状态
cat /proc/sched_debug | head -40
perf sched:调度延迟分析
perf sched record -- sleep 5
perf sched latency # 延迟分布
perf sched map # CPU时间线
perf sched script # 原始事件
/proc/[pid]/sched:单进程调度信息
cat /proc/self/sched | head -20
# 字段:vruntime、exec_start、sum_exec_runtime、nr_migrations
关键参数:sched_min_granularity_ns、sched_wakeup_granularity_ns、sched_migration_cost_ns、sched_autogroup_enabled
11. 实战案例
场景1:低延迟服务——nice -n -10提升优先级,或SCHED_FIFO,降低min_granularity_ns
场景2:批处理隔离——nice -n 19或chrt -b 0设为SCHED_BATCH
场景3:限制后台CPU——cgroup cpu.max"50000 100000"限制为单核50%
12. 总结
CFS通过红黑树+vruntime的精妙组合实现高效公平调度。理解核心机制(vruntime、权重、调度粒度、负载均衡)对性能调优至关重要。合理设置nice值、cgroup隔离、SMP负载均衡和NUMA策略,可使系统在各类负载下保持最佳表现。

发表评论 取消回复