是的,CFS(Completely Fair Scheduler,完全公平调度器)是 Linux 内核默认的进程调度器,自 2007 年 Linux 2.6.23 版本起取代了早期的 O(1) 调度器。它的核心目标是公平地为所有可运行进程分配 CPU 时间,同时保持高响应性和吞吐量。
CFS 的核心原理
-
虚拟运行时间(vruntime)
- 每个进程有一个
vruntime
(虚拟运行时间),记录其在 CPU 上运行的时间经过优先级加权后的值。 - 优先级权重:进程的
nice
值(优先级)会影响vruntime
的增速。高优先级(低nice
值)的进程vruntime
增长更慢,从而更频繁地被调度。
- 每个进程有一个
-
红黑树管理进程队列
- CFS 使用红黑树(一种高效的自平衡二叉搜索树)按
vruntime
排序所有可运行进程。 - 每次调度时,选择
vruntime
最小的进程(最左侧节点)运行,确保公平性。
- CFS 使用红黑树(一种高效的自平衡二叉搜索树)按
-
时间片动态调整
- 不依赖固定时间片,而是根据进程数量和系统负载动态调整每个进程的运行时间。
- 核心参数
sched_latency
(默认 24ms):保证所有可运行进程至少在该周期内运行一次。
CFS 的优势
-
公平性
- 所有进程(包括交互式任务和后台进程)按权重公平分享 CPU,避免饥饿问题。
-
低延迟
- 交互式进程(如 GUI 应用)因
vruntime
累积较慢,能更快被调度,提升用户体验。
- 交互式进程(如 GUI 应用)因
-
多核扩展性
- 为每个 CPU 核心维护独立的红黑树,减少锁竞争,适应多核/多线程环境。
-
动态优先级
- 结合
nice
值调整权重,允许用户或系统管理员灵活控制进程优先级。
- 结合
CFS 的配置与调优
-
调度策略参数
SCHED_NORMAL
:默认策略,用于普通进程。SCHED_BATCH
:适合后台任务,减少抢占频率。SCHED_IDLE
:极低优先级,仅当系统空闲时运行。
-
调整内核参数
/proc/sys/kernel/sched_latency_ns
:调度周期时长(纳秒)。/proc/sys/kernel/sched_min_granularity_ns
:进程最小运行时间(避免频繁切换开销)。
-
cgroups 控制
- 通过
cpu.shares
为进程组分配 CPU 资源权重,例如在容器中限制资源使用。
- 通过
常见问题与诊断
-
CPU 饥饿问题
- 使用
perf sched
或/proc/<PID>/sched
查看进程的vruntime
和调度延迟。 - 检查是否有高优先级进程(如实时进程
SCHED_FIFO
)垄断 CPU。
- 使用
-
性能调优
- 调整
sched_migration_cost
避免进程在 CPU 间频繁迁移。 - 对延迟敏感任务使用
SCHED_RR
(实时轮转策略)。
- 调整
示例:查看进程调度信息
# 查看某个进程的调度状态
cat /proc/<PID>/sched
# 监控调度事件(需 root)
perf sched record -a sleep 1
perf sched latency
CFS 通过数学上的公平分配模型(基于虚拟时间和红黑树)实现了高效且灵活的调度,是 Linux 高并发性能的重要基石。如果需要深入细节,可以进一步研究内核源码中的 kernel/sched/fair.c
。