CFS调度源码:从 schedule() 到pick_next_entity 的vruntime 公平

线上 CPU 打满、延迟抖动、D 状态误判,根因常在调度路径。本文沿 schedule() → __schedule() → CFS pick_next_entity() 走通一次选路,用真实文件定位 vruntime 与红黑树,方便对照 perf sched / schedstat 验证。

源码锚点

路径 作用
kernel/sched/core.c schedule()、__schedule()、上下文切换入口
kernel/sched/fair.c CFS:entity_tick、update_curr、pick_next_entity
include/linux/sched.h task_struct、sched_entity
include/linux/sched/sysctl.h 调度相关 sysctl
Documentation/scheduler/sched-design-CFS.rst CFS 设计说明

核心结构(节选概念):

c 复制代码
/* include/linux/sched.h --- sched_entity */
struct sched_entity {
	struct load_weight	load;
	struct rb_node		run_node;
	u64			vruntime;
	/* ... */
};

struct task_struct {
	struct sched_entity	se;
	const struct sched_class *sched_class;
	/* ... */
};

选路骨架:

c 复制代码
/* kernel/sched/core.c --- 概念路径 */
asmlinkage __visible void __sched schedule(void)
{
	struct task_struct *tsk = current;
	sched_submit_work(tsk);
	__schedule(SM_NONE);
	sched_update_worker(tsk);
}

调用链

text 复制代码
用户态阻塞 / 时间片耗尽 / 抢占点
  → schedule()                     /* core.c */
      → __schedule(sched_mode)
          → pick_next_task(rq, prev, &rf)
              → 按优先级扫 sched_class
                  → fair_sched_class.pick_next_task
                      → pick_next_entity(cfs_rq)
                          → 红黑树最左 = 最小 vruntime
              → context_switch(prev, next)
                  → switch_mm / switch_to

时钟滴答侧:

text 复制代码
scheduler_tick
  → task_tick_fair
      → entity_tick → update_curr
          → 累加 delta_exec,换算进 se->vruntime

重点知识

1. vruntime 是公平的尺子

CFS 不按固定时间片轮转,而按 虚拟运行时间 排序。nice 通过权重放大/缩小同一墙上时间对应的 vruntime 增量:nice 越小,同等墙钟时间里 vruntime 涨得越慢,树中越靠左,越容易被再次选中。

2. 红黑树只存可运行实体

cfs_rq->tasks_timeline 上每个可运行 sched_entity 一个节点;pick_next_entity 取最左。入队 enqueue_entity、出队 dequeue_entity 必须与状态机一致,否则会出现「看起来 RUN 却不在树上」。

3. 调度类分层

stop > dl > rt > fair > idle。普通业务几乎都在 fair;实时任务走 rt/dl,不会与 CFS 争同一把 vruntime 尺。排障时先分清任务是否被绑到 RT。

4. 配置与观测

bash 复制代码
# 调度统计(需 CONFIG_SCHEDSTATS)
grep -E 'sched_' /proc/self/sched
cat /proc/schedstat | head
# 延迟剖析
perf sched record -a -- sleep 5
perf sched latency
# nice / 亲和
chrt -m
taskset -pc <pid>

常见 sysctl(名称随内核略有差异,以本机 sysctl -a | grep sched 为准):kernel.sched_latency_ns、kernel.sched_min_granularity_ns。

5. 设计意图与踩坑

  • 意图:多任务长期公平,短任务延迟可控。
  • 坑 :把 D(TASK_UNINTERRUPTIBLE)当 CPU 忙------它常在等 I/O,加核无效。
  • 坑 :容器未设 cpu.max / cpuset,与宿主机抢同一 CFS 池。
  • 坑:持锁过久导致调度延迟,表现为尾延迟而非平均 CPU。

Checklist

  • 能指出 schedule → __schedule → pick_next_task → CFS 的文件位置
  • 解释 vruntime 与 nice 权重的关系,并用 /proc/<pid>/sched 对照
  • 区分 fair / rt 调度类,避免用 CFS 参数调实时任务
  • 用 perf sched latency 或 schedstat 看到排队延迟
  • 排查高 load 时先区分 RUN 排队 vs D 状态等盘
  • 容器场景检查 cpu / cpuset 限额,避免无界争抢
相关推荐
FPGA信号处理11 小时前
【人工神经网络】第一讲:竞争网络与自组织特征映射:从胜者为王到保序映射
网络
吴声子夜歌11 小时前
Kubernetes权威指南——Kubernetes安装配置指南(网络配置)
网络·容器·kubernetes
考拉讲支付12 小时前
延迟分账 / 核销分账的技术实现方案:服务完成后再分钱,到底怎么设计?
大数据·运维·人工智能·微信小程序·小程序·系统架构
硅基造物主12 小时前
STM32 从 0 到 1 做智能家居(十二):USART2 分时复用 —— ESP-12F + MQTT
网络·stm32·mqtt·智能家居·esp-12f
我不会起名字32212 小时前
TCP 三次握手为什么是三次:丢包、重传与初始序列号
网络·tcp·原理·握手
ADAI_Bowen12 小时前
写文章 - 知乎
大数据·运维·人工智能
Yang961112 小时前
鼎讯信通DXA-3S光纤熔接机:光缆教学中的技术精粹解析
网络
GeW12 小时前
新质生产力路线图解读:数据库性能优化与Linux调优专场
linux
云宏信息13 小时前
超融合和存算分离怎么选?从性能、可靠性、扩展、成本四个维度讲述如何精准匹配架构选型 | 附企业降本轻量云方案
运维·服务器·架构·云计算
xbzb13 小时前
IP、掩码、网关、DNS 到底谁管什么?网络基础与七种设备一次讲清
网络·网关·mac·ip·dns·掩码