接前一篇文章:Linux CFS(完全公平调度器)原理与实现细节全解析(2)
二、核心概念与关键抽象
2.3 CFS运行队列(cfs_rq)与红黑树
每个CPU都维护一个就绪队列struct rq,其中CFS使用自己的子结构struct cfs_rq管理所有属于CFS调度类的可运行实体。
cfs_rq的核心成员之一是一棵按vruntime排序的红黑树:
-
所有处于TASK_RUNNING状态的sched_entity都在这棵树上;
- 树中最左节点就是vruntime最小的任务,即下一个最该运行的任务;
- 插入/删除/查找均为 O(log N),在任务数很大时仍然可控。
红黑树的存在,使得CFS可以用非常简洁的逻辑实现:
“永远选择vruntime最小的任务运行”
典型操作如下:
enqueue_entity()
新任务就绪 / 唤醒 → 插入rb-tree;
dequeue_entity()
任务阻塞 / 退出 → 从rb-tree移除;
pick_next_task_fair()
取 rb-tree 最左节点 → 下一个运行任务。
同时,cfs_rq中还维护一个关键字段:
min_vruntime
当前运行队列中所有实体vruntime的下界近似值,主要用于新任务vruntime初始化与全局“时间对齐”。
2.4 权重、nice值与调度粒度
在Linux中:
- nice值范围为[-20, +19],数值越小优先级越高;
-
CFS使用
sched_prio_to_weight[]将nice值映射为整数权重weight; - 权重近似呈指数级变化:每降低1个nice,权重大约乘以1.25。
例如(示意):
- nice = 0 → weight = 1024;
- nice = -1 → weight ≈ 1277;
- nice = +1 → weight ≈ 820。
CFS使用如下公式更新vruntime:
[ \Delta \text{vruntime} = \Delta t_\text{exec} \times \frac{\text{NICE_0_LOAD}}{\text{weight}} ]
因此:
- 权重越大(nice越低),同样运行1ms,其vruntime增加得更少;
- 权重越小(nice越高),vruntime增加得更多,在红黑树中更容易被“推到右边”,降低调度频率。
此外,为避免过度频繁的上下文切换,CFS引入了几个重要参数:
sched_min_granularity
最小调度粒度(默认约 0.75ms),单次调度不希望明显短于该值;
sched_latency
目标调度延迟(默认约 6ms),即当可运行任务数较少时,每个任务在一个周期内大致能运行一次;
-
当任务数
nr_running较多时,sched_latency会按nr_running sched_min_granularity动态放大,以避免极端高频切换。
更多内容请看下回。
290

被折叠的 条评论
为什么被折叠?



