CFS 调度器是什么
CFS 是完全公平调度器,Linux 从 2.6.23 起作为普通进程的默认调度策略。它给每个可运行任务维护一个 vruntime,即按权重折算后的累计运行时间;调度时总是挑选 vruntime 最小的任务执行,红黑树就是这个选择过程的数据结构。权重由 nice 值映射而来,nice 每相差一级权重约差 1.25 倍,因此「公平」指的是按权重比例分配 CPU 时间,而不是每个任务平均分到相同的时间片。
基本信息
| 核心量 | vruntime,按权重折算的累计运行时间 |
|---|---|
| 选择结构 | 红黑树,取 vruntime 最小的任务 |
| 权重来源 | nice 值映射的权重表,nice 每级权重约差 1.25 倍 |
| nice 范围 | -20(最高优先级)到 19(最低),默认 0 |
| 观测入口 | /proc/sched_debug(需权限)、/proc/<pid>/sched、pidstat |
| 版本变化 | 较新内核引入 EEVDF 调度模型,具体行为以所用内核版本为准 |
典型使用场景
- 理解 CPU 竞争:多个任务争抢同一颗核时,按 nice 比例分配才能解释观测结果
- 调优批处理任务:把后台任务降 nice,让在线业务优先获得 CPU
- 排查不公平现象:预期按比例分配却严重偏斜时,检查 cgroup 权重与 CPU 亲和性
- 容器限额规划:cgroup 的 cpu.weight 与 nice 是两套权重体系,需要理清各自作用
- 性能分析:结合 /proc/<进程>/sched 看实际运行时间与切换情况
观察与调整
观察与调整
ps -eo pid,ni,pri,pcpu,comm --sort=-pcpu | head # 查看 nice 与实际占用
nice -n 10 tar czf backup.tar.gz /data # 以较低优先级运行
renice -n 5 -p 12345 # 调整已运行进程的 nice
cat /proc/sched_debug | head -30 # 需权限,查看调度实体信息
cat /proc/12345/sched | grep -E 'nr_switches|se.sum_exec' # 单进程调度统计
cat /sys/fs/cgroup/cpu.weight 2>/dev/null # cgroup v2 权重权重与时间分配
| 概念 | 含义 | 判读要点 |
|---|---|---|
| vruntime | 按权重折算的累计运行时间 | 调度器总选最小者,体现比例而非绝对优先级 |
| nice | 静态优先级,范围 -20 到 19 | 每级权重约差 1.25 倍,实际是比例关系 |
| cgroup 权重 | cgroup v2 的 cpu.weight | 作用于分组之间,与进程 nice 是两套体系 |
| 切换统计 | /proc/<pid>/sched 中的切换计数 | 结合运行时间判断任务实际得到的份额 |
nice 调整的是 CPU 分配比例,不是让任务彻底停摆:即使把 nice 提到 19,在系统不太忙时它依然能跑满 CPU。真正需要硬性隔离时应使用 CPU 亲和性绑定或 cgroup 配额。
留意内核版本差异:较新内核引入了新的调度模型,公平性的具体实现与老版本 CFS 不完全一致。跨版本对比调优结论前,先确认两端内核的行为是否可比。