进程调度是操作系统内核的核心组成部分,负责在多个可运行进程之间分配 CPU 时间,确保系统的响应速度、公平性和吞吐量。由 Ben Lyvet 在 2023 年提出的 EEVDF(Earliest Eligible Virtual Deadline First)调度器在 Linux 6.6 中正式替代了沿用十余年的 CFS 作为默认调度类,标志着 Linux 调度器进入新的里程碑。 理解 Linux 调度器需要掌握的关键概念: Ingo Molnar 在 2007 年向 Linux 2.6.23 中引入 CFS,替代了 O(1) 调度器。其核心思想是:在理想的多任务处理器上,每个进程应获得 1/N 的 CPU 时间。 每个进程经历的虚拟运行时间(virtual runtime)用于衡量该进程相对于其他进程的公平程度。计算公式如下: 核心要点:优先级越高(nice 值越低)的进程,其 vruntime 增长越慢,从而可以获得更多 CPU 时间。这一机制本质上实现了按权重比例分配 CPU 的理想模型。 CFS 使用红黑树来组织运行队列,每个 CPU 的 rq->cfs.tbr 指向一个红黑树。关键设计如下: 调度周期是指每个可运行进程至少被调度一次的时间窗口。计算公式为: 其中 sysctl_sched_latency 默认 20ms,sysctl_sched_min_granularity 默认 2.5ms。当运行中的进程数增多时,周期会按比例扩展以保证每个进程至少获得最小粒度的时间片。 每个进程分配的时间片 = 调度周期 / 运行中进程总数。但 CFS 的目标是不固定时间片,而是通过 vruntime 追踪公平性。进程的时间片会根据权重调整:高权重进程获得更长CPU时间但 vruntime 增长更慢,低权重进程则相反。 可通过 /proc/[pid]/sched 中的 nr_voluntary_switches 和 nr_involuntary_switches 观察切换模式。如果 involuntary 切换过高,可能说明时间片过短或系统负载过重。 CFS 虽然实现了公平调度,但在某些场景下存在不足:当大量进程同时变为可运行时,CFS 的周期扩展机制会导致某些进程等待过长时间才能获得首次执行。EEVDF 通过引入明确的虚拟截止时间(virtual deadline)来解决这个问题。 EEVDF 与 CFS 的主要区别体现在四个方面。首先排序依据不同:CFS 按 vruntime 最小优先,EEVDF 按 eligible deadline 最小优先。其次时间片分配方式不同:CFS 基于权重比例动态计算,EEVDF 使用基于最小粒度参数的固定粒度分配。第三是可运行准入条件不同:CFS 仅检查 nr_running 数量,EEVDF 还需满足 lag >= 0 的滞后验证。最后延迟保证不同:CFS 无明确保证,EEVDF 的虚拟截止时间等于当前时间加上时间片乘以权重因子。 EEVDF 引入了两个关键概念确保公平性。第一个是 eligibility(资格):进程必须在当前时间已经到达其 eligibility_time 后才被视为候选者,防止新唤醒的进程抢占已经在运行的进程。第二个是 lag(滞后):lag = virtual_time - ideal_virtual_time,表示某进程实际获得的CPU时间与其应得时间的偏差。EEVDF 保证每个进程的 lag 始终在 [-sched_granularity, +sched_granularity] 范围内。 根据 Peter Zijlstra 的测试数据,EEVDF 在高负载场景下的响应性提升显著:桌面场景延迟降低 20-40%,编译等高并发负载下吞吐量略有下降但公平性大幅改善。对于延迟敏感型应用(如音频、游戏),EEVDF 减少了对 sched_wakeup_granularity 的依赖,提供了更可预测的调度延迟。 在 KVM/QEMU 虚拟机中,调度器需要处理 VCPU(虚拟 CPU)的调度。Guest 内部的进程调度器(CFS/EEVDF)与 Host 的调度器形成两层调度结构。当 VCPU 在 Host 上被抢占时,Guest 内部的 steal time 会增加。Host 调度器(通常也是 EEVDF/CFS)将 VCPU 视为普通进程进行调度。virtio 驱动和 vhost 线程的优先级需要与 VCPU 同步配置。 本文基于 Linux 6.8 内核源码分析,结合 sched(7) 手册、Peter Zijlstra 的提交说明及相关论文整理而成。随着内核持续演进,调度器的实现细节可能进一步调整,建议读者结合具体内核版本查阅最新源码。Linux 内核进程调度器深度实战:从 CFS 到 EEVDF 的演进与实现
一、调度器的核心概念
二、CFS 完全公平调度器的设计哲学
2.1 vruntime 概念
vruntime += (实际运行时间 * NICE_0_LOAD) / 进程权重
2.2 红黑树(Red-Black Tree)
/* CFS 运行队列核心结构 */
struct cfs_rq {
unsigned long nr_running; /* 运行中的进程数 */
struct rb_root_cached tbr; /* 红黑树根 */
struct rb_node *leftmost; /* 缓存的最左节点 */
u64 min_vruntime; /* 最小 vruntime,用于基准校准 */
};
三、调度周期与时间片管理
3.1 调度周期(sched_period)
sched_period = max(sysctl_sched_latency, nr_running * sysctl_sched_min_granularity)
3.2 时间片计算
3.3 关键 sysctl 参数
kernel.sched_latency_ns = 24000000 (24ms,目标调度延迟)
kernel.sched_min_granularity_ns = 3000000 (3ms,最小时间片粒度)
kernel.sched_wakeup_granularity_ns = 4000000 (4ms,抢占粒度阈值)
kernel.sched_migration_cost_ns = 500000 (0.5ms,迁移成本估计)
四、进程状态机与上下文切换
4.1 Linux 进程状态
TASK_RUNNING (0x0000) -- 正在运行或在运行队列中等待
TASK_INTERRUPTIBLE(0x0001) -- 可中断睡眠(等待事件/信号)
TASK_UNINTERRUPTIBLE(0x0002) -- 不可中断睡眠(通常等待I/O)
TASK_STOPPED (0x0004) -- 收到 SIGSTOP/SIGTSTP 停止运行
TASK_TRACED (0x0008) -- 被 ptrace 跟踪
EXIT_ZOMBIE (0x0020) -- 已退出但未被 wait 回收
EXIT_DEAD (0x0040) -- 完全消亡(已被回收)
4.2 上下文切换的两种类型
五、EEVDF 调度器:Linux 6.6 的新时代
5.1 EEVDF 的设计动机
5.2 EEVDF 核心概念
5.3 EEVDF 的 eligibility 与 lag 机制
5.4 性能影响
六、调度器调试与性能分析
6.1 常用监控指标
# 查看单个进程的调度统计
cat /proc/[pid]/sched
# 输出示例(关键字段):
# cat - 进程 PID
# vruntime 1234567 - 虚拟运行时间 (ns)
# sum_exec_runtime 1234567890 - 总运行时间 (ns)
# nr_switches 12345 - 上下文切换总次数
# nr_voluntary_switches 10000 - 自愿切换次数
# nr_involuntary_switches 2345 - 非自愿切换次数
# load_weight 1024 - 权重(对应 nice 0)
# policy 0 - 调度策略 (0=SCHED_NORMAL)
6.2 性能分析工具
# 统计上下文切换频率
perf stat -e sched:sched_switch ./workload
# 追踪调度器决策路径
echo 1 > /sys/kernel/debug/tracing/events/sched/enable
cat /sys/kernel/debug/tracing/trace_pipe
# 分析 CPU 时间分布
perf top -e cycles
# 检查 steal time(虚拟化场景)
grep -E 'cpu|steal' /proc/stat
# 使用 BPF 追踪调度延迟
bpftrace -e 'tracepoint:sched:sched_wakeup { @ latency = nsecs - args->common_timestamp; }'
七、最佳实践与调优建议
八、虚拟化环境下的调度特性
# 诊断 steal time 问题
$ top -1 # 查看 %st 列
$ cat /proc/stat | grep 'cpu' # 查看 steal 计数器
# 优化方案:
# 1. 使用 isolcpus 隔离核心给 VCPU
# 2. 设置 VCPU 线程为 FIFO 策略(chrt -f -p 50 [vcpu_pid])
# 3. 调整 Host 的 sched_min_granularity_ns 减少抢占

发表评论 取消回复