Linux内核进程调度器深度实战:CFS完全公平调度与实时调度类全景解析

摘要:全面解析 Linux 内核进程调度子系统的核心机制,深入剖析 CFS(完全公平调度器)的红黑树运行时计算模型、虚拟运行时间、组调度与带宽控制,涵盖实时调度类 SCHED_FIFO/SCHED_RR/SCHED_DEADLINE 的设计原理与实战配置,并通过 /proc/sys/kernel 调优参数、taskset/cgroup 绑定策略、ftrace 跟踪手段展示生产环境中的调度器调优方法。

1. 调度器架构总览

Linux 内核调度器采用分级调度类(sched_class)设计,按优先级依次遍历各调度类,选择下一个要运行的进程。6.x 内核中核心调度类包括:

SCHED_DEADLINE(EDF Deadline)→ SCHED_FIFO/SCHED_RR(实时)→ SCHED_NORMAL/CFS(普通)→ SCHED_IDLE(空闲)。每个调度类通过 pick_next_task() 方法提供候选进程,调度器按优先级降序调用。

CFS 是 Linux 默认的普通调度算法,其设计理念源于 Con Kolivas 的 RSDL(旋转楼梯deadline调度器),核心思想是让每个可运行进程的"虚拟运行时间"趋于一致,从而实现"完全公平"。

2. CFS 核心数据结构

CFS 的核心是红黑树(struct rb_root_cached),以 vruntime(虚拟运行时间)为键值。关键结构体:

  • struct sched_entity:每个进程/调度组的调度实体,包含 vruntime、load_weight(权重)等字段
  • struct cfs_rq:CFS 运行队列,持有红黑树根节点 tasks_timeline,以及 min_vruntime(队列最小 vruntime)
  • struct task_group:组调度结构,支持 cgroup v2 的 cpu.max 带宽控制
  • struct rq:每个 CPU 核心的全局运行队列,包含指向当前运行进程 curr 和 CFS 运行队列 cfs 的指针

进程的 vruntime 增长公式为:vruntime = delta_exec * NICE_0_LOAD / weight。其中 NICE_0_LOAD 是 nice=0 时的基准权重(1024),weight 随 nice 值变化(每级相差约10%,乘数系数为 1.25)。这意味着低 nice 值(更高优先级)进程积累 vruntime 更慢,更频繁获得 CPU 时间。

3. CFS 调度算法详解

3.1 入队与出队

当进程变为可运行状态(wakeup/fork),调用 enqueue_entity() 将 sched_entity 插入红黑树的最左可用节点。同时更新 cfs_rq->min_vruntime,保证新进程的 vruntime 不会过小,避免新进程 Starvation。

出队时调用 dequeue_entity(),从红黑树移除节点,并运行 __dequeue_entity() 维护 leftmost 指针。

3.2 选择下一个进程

pick_next_task_fair() 是 CFS 的核心选择函数:

  1. 获取红黑树最左侧节点(最小 vruntime)
  2. 如果当前进程仍属于 CFS 类且有剩余时间片,将其重新入队
  3. 调用 set_next_entity() 将选中的 sched_entity 设置为 cfs_rq-
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部