sched-ext discussion
[PATCH v3] docs/sched_ext: document that cgroup CPU knobs are scheduler-dependent
LLM 分析
sched_ext 文档:cgroup CPU 旋钮由调度器决定
系列概况
- 标题:
[PATCH v3] docs/sched_ext: document that cgroup CPU knobs are scheduler-dependent - 作者:Tao Cui cuitao@kylinos.cn
- 版本:v3(单 patch 系列,从 v2 起只修改
Documentation/scheduler/sched-ext.rst) - 规模:1 个文件,12 行新增
- 修改文件:
Documentation/scheduler/sched-ext.rst - 代码统计:+12 / -0(一段纯文档,无 C 代码改动)
- Message-ID:首发
20260824091501.547649-1-cui.tao@linux.dev,回复aowxJK_KgBLLnyiN@gpd4、1b2f54bd-97f5-4175-9a92-34871dd6f375@linux.dev - 完整性:发起邮件与两位回复邮件 body 都被截断(lore 抓取不完整),但 patch 主体从 v2 起就稳定,hunk 与签名行可重建
补丁目的
让用户明确区分 fair 调度器 与 sched_ext 调度器 在 cgroup CPU 控制接口上的语义差异:
- fair(内核内置 CFS)会 强制执行
cpu.max、cpu.weight、cpu.idle等 cgroup v2 CPU 控制文件; - sched_ext 只是把这些数值 透传 给当前装载的 BPF 调度器,由后者决定是否实现、是否部分实现;
- 提醒 nice 等传统接口同样依赖 BPF 调度器自身的实现。
修复的问题是:用户和容器编排器常误以为写在 cgroup 里的所有 CPU 限制都是内核语义,把 CPU 配额绑定到容器时可能在切到 sched_ext 后"失效",但其实是调度器没实现。
旧流程的问题
文档的 basics 章节只举了 BPF struct 例子和 simple scheduler,没有解释 cgroup 接口在 sched_ext 模型下的语义发生了什么变化。读者默认以为内核兜底,导致部署到生产时 cpu.max 数值与实际节流行为不一致。
新流程
新增一节 Scheduler-Dependent Knobs,用 12 行文字说明:
- fair 在内核侧强制 cgroup v2 CPU 旋钮;
- sched_ext 只负责调用
ops.cgroup_set_weight()、cgroup_set_idle()、cgroup_set_bandwidth()等回调; - 这些回调是否被实现、实现到什么程度,都取决于装载的 BPF 调度器;
- nice 等其他旋钮同理;
- 依赖时查阅装载的调度器自身文档或源码。
关键实现
patch 仅有 1 个 hunk,落在 sched-ext.rst 第 242 行附近(紧接 simple struct 示例块)。要点:
+Scheduler-Dependent Knobs
+-------------------------
+
+The fair class enforces cpu controller knobs such as ``cpu.max``,
+``cpu.weight`` and ``cpu.idle`` in the kernel. sched_ext only passes
+them to the BPF scheduler through ``ops.cgroup_set_weight()``,
+``ops.cgroup_set_idle()``, ``ops.cgroup_set_bandwidth()`` and friends.
+Whether and how a knob takes effect is up to the loaded scheduler: it
+may implement the corresponding callback partially or not at all. The
+same applies to other knobs like nice levels. When relying on these
+knobs, check the documentation or source of the loaded scheduler.
无新增 C 头文件、无 ops 改动、无示例 BPF 代码;从 v2 → v3 去掉了具体调度器名单与 nr_throttled 例子,按评审要求保持章节通用、简洁。
/* 概念上原本依赖这些内核路径(不再适用 sched_ext) */
int cpu_weight_write_u64(struct cgroup_subsystem_state *css,
struct cftype *cft, u64 val);
void cgroup_set_bandwidth(struct task_group *tg, u64 period, u64 quota);
类比
把 fair 调度器想成 公司自营餐厅——菜单(cpu.max 等)一写下去,后厨就照单出餐并强制执行;把 sched_ext 想成 外包食堂——菜单写下去只是通知外包服务商,由他们决定是否照做、做几分。用餐高峰(cpu.idle、nice 提升)能不能真正得到好位置,要看外包(BPF 调度器)配不配合。
流程图
cgroup v2 CPU 文件
(cpu.max / cpu.weight /
cpu.idle)
|
| 内核解析 + subsys dispatch
v
+----------------------+ 是 fair? +---------------------+
| fair (CFS) 强制执行 | ----------------------> | nr_throttled++ |
+----------------------+ | throttled_runnable|
| +---------------------+
| 否(sched_ext)
v
+----------------------+ ops.cgroup_set_*() +-------------------+
| sched_ext 透传 | -------------------------> | BPF 调度器决定 |
+----------------------+ | 实现 / 部分 / 不实现|
+-------------------+
Highlight:风险与注意点
- 风险 1(用户预期):把 K8s
cpu.limits配进容器并启用sched_ext后,可能完全不等价于"硬限"。运维需要在切调度器前压测。 - 风险 2(API drift):本节列举的
ops.cgroup_set_weight() / set_idle() / set_bandwidth()是当前名字,未来回调新增或改名(如cgroup_set_lbandwidth)后这段文字会过时,需要同步更新。 - 风险 3(部分实现):同一个 BPF 调度器可能只接
cpu.weight不接cpu.idle,业界缺少统一的"能力位图"告诉用户哪些旋钮生效,将来最好补一个scx_capabilities或 README 字段。 - 跟进点:Andrea Righi 在 v2 评审里要求"concise and generic",Tao 在 v3 删掉了具体调度器名单,措辞是否还需要再 polish,可关注后续维护者收尾 ack。
版本变化
- v2 → v3:删除调度器具体名单与
nr_throttled示例,仅保留通用描述以避免文档被某个具体实现绑定。 - v1 → v2(根据
Documentation/scheduler/sched-ext.rst | 12 ++++++++++++反推):仅做最小调整,主体章节已经稳定,新增位置不变。
一句话总结
这是 sched_ext 文档的一次小补丁:补一节"Scheduler-Dependent Knobs",明确告诉用户 cgroup v2 的 CPU 旋钮在 sched_ext 下由 BPF 调度器自行解释,fair 的强制语义不再兜底。