基于 Linux 6.18.26,结合内核源码逐行分析
系列文章:
- 前言:sched_ext 框架总览
- Sched_ext 回调深度解析(一):init_task ------ 每个任务走进调度器的第一道门(6.18.26)
- Sched_ext 回调深度解析(二):enable ------ 任务被调度器接管的关键时刻(6.18.26)
- Sched_ext 回调深度解析(三):select_cpu ------ 任务唤醒时的选核决策(6.18.26)
- Sched_ext 回调深度解析(四):runnable ------ 任务状态转换的哨兵(6.18.26)
- Sched_ext 回调深度解析(五):enqueue ------ 任务入队,调度器的核心决策点(6.18.26)
- Sched_ext 回调深度解析(六):dispatch ------ 从队列取出任务送到 CPU(6.18.26)
- Sched_ext 回调深度解析(七):running ------ 任务开始执行(6.18.26)
1. sched_ext 是什么
sched_ext(简称 scx)是 Linux 内核的 eBPF 调度器框架,自 6.12 起合入主线。它允许开发者用 eBPF 程序在用户态编写自定义 CPU 调度策略,而无需修改内核代码或重启系统。
传统上,添加一个新的 Linux 调度器意味着编写一个完整的 sched_class,直接操作内核内部数据结构------这需要内核开发 expertise,修改后必须重新编译、重启才能生效。sched_ext 改变了这个局面:内核提供了一个标准的回调接口(struct sched_ext_ops),开发者只需用 BPF 程序实现这些回调,就能定义一个完整的调度策略。调度器程序可以热加载、热卸载,切换策略时系统中的任务会自动平滑迁移。
可以把 sched_ext 理解为一个"调度器插件系统"------内核在关键调度时机(任务唤醒、入队、出队、开始执行、让出 CPU 等)调用 BPF 回调,BPF 程序在回调中做出调度决策。
1.1 框架总览
#mermaid-svg-twynHwBSqktVInDB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-twynHwBSqktVInDB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-twynHwBSqktVInDB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-twynHwBSqktVInDB .error-icon{fill:#552222;}#mermaid-svg-twynHwBSqktVInDB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-twynHwBSqktVInDB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-twynHwBSqktVInDB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-twynHwBSqktVInDB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-twynHwBSqktVInDB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-twynHwBSqktVInDB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-twynHwBSqktVInDB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-twynHwBSqktVInDB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-twynHwBSqktVInDB .marker.cross{stroke:#333333;}#mermaid-svg-twynHwBSqktVInDB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-twynHwBSqktVInDB p{margin:0;}#mermaid-svg-twynHwBSqktVInDB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-twynHwBSqktVInDB .cluster-label text{fill:#333;}#mermaid-svg-twynHwBSqktVInDB .cluster-label span{color:#333;}#mermaid-svg-twynHwBSqktVInDB .cluster-label span p{background-color:transparent;}#mermaid-svg-twynHwBSqktVInDB .label text,#mermaid-svg-twynHwBSqktVInDB span{fill:#333;color:#333;}#mermaid-svg-twynHwBSqktVInDB .node rect,#mermaid-svg-twynHwBSqktVInDB .node circle,#mermaid-svg-twynHwBSqktVInDB .node ellipse,#mermaid-svg-twynHwBSqktVInDB .node polygon,#mermaid-svg-twynHwBSqktVInDB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-twynHwBSqktVInDB .rough-node .label text,#mermaid-svg-twynHwBSqktVInDB .node .label text,#mermaid-svg-twynHwBSqktVInDB .image-shape .label,#mermaid-svg-twynHwBSqktVInDB .icon-shape .label{text-anchor:middle;}#mermaid-svg-twynHwBSqktVInDB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-twynHwBSqktVInDB .rough-node .label,#mermaid-svg-twynHwBSqktVInDB .node .label,#mermaid-svg-twynHwBSqktVInDB .image-shape .label,#mermaid-svg-twynHwBSqktVInDB .icon-shape .label{text-align:center;}#mermaid-svg-twynHwBSqktVInDB .node.clickable{cursor:pointer;}#mermaid-svg-twynHwBSqktVInDB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-twynHwBSqktVInDB .arrowheadPath{fill:#333333;}#mermaid-svg-twynHwBSqktVInDB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-twynHwBSqktVInDB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-twynHwBSqktVInDB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-twynHwBSqktVInDB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-twynHwBSqktVInDB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-twynHwBSqktVInDB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-twynHwBSqktVInDB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-twynHwBSqktVInDB .cluster text{fill:#333;}#mermaid-svg-twynHwBSqktVInDB .cluster span{color:#333;}#mermaid-svg-twynHwBSqktVInDB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-twynHwBSqktVInDB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-twynHwBSqktVInDB rect.text{fill:none;stroke-width:0;}#mermaid-svg-twynHwBSqktVInDB .icon-shape,#mermaid-svg-twynHwBSqktVInDB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-twynHwBSqktVInDB .icon-shape p,#mermaid-svg-twynHwBSqktVInDB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-twynHwBSqktVInDB .icon-shape .label rect,#mermaid-svg-twynHwBSqktVInDB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-twynHwBSqktVInDB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-twynHwBSqktVInDB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-twynHwBSqktVInDB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 内核空间
用户空间
sched_ext 框架 (kernel/sched/ext.c)
实现 ops 回调
加载/卸载 BPF 程序
读写
查询/更新
调用 sched_class 方法
触发 ops 回调
ext_sched_class
enqueue_task_scx
dequeue_task_scx
balance_scx
pick_task_scx
put_prev_task_scx → stopping
set_next_task_scx → running
BPF 调度器程序
(实现 sched_ext_ops)
用户态工具
(scx CLI / 自定义工具)
struct sched_ext_ops
回调钩子集合
DSQ 调度队列
(Dispatch Queues)
任务状态机
(scx_task_state)
内核核心调度器
(kernel/sched/core.c)
从上图可以看出整个框架的运作方式:
- 开发者编写 BPF 调度器程序 ,实现
struct sched_ext_ops中定义的回调函数。 - 用户态工具将 BPF 程序加载到内核,内核注册这些回调。
- 内核核心调度器 在调度事件发生时,调用
ext_sched_class中对应的方法。 ext_sched_class的方法触发 BPF 回调,BPF 程序在回调中做出调度决策(如选择 CPU、入队到哪个 DSQ、从哪个 DSQ 取出任务等)。- **DSQ(Dispatch Queue)**是 BPF 调度器和内核之间的任务交换枢纽------BPF 程序将任务放入 DSQ,内核从 DSQ 中取出任务送到 CPU。
2. 完整回调总览
2.1 回调一览表
struct sched_ext_ops 代表一个 BPF 调度器,其中定义了多个回调函数。下表列出了所有核心回调:
| 钩子 | 触发次数 | 含义 |
|---|---|---|
init_task |
每个 task 仅一次 | "登记"------task 被 scx 框架认识 |
enable |
每个 task 仅一次 | "上岗"------task 被 scx 正式接管 |
select_cpu |
每次唤醒时 | "选座"------task 醒来时选择目标 CPU |
runnable |
每次变为可运行时 | "就位"------通知 task 变为 runnable |
enqueue |
每次入队时 | "排队"------task 被放入调度队列 |
dispatch |
每次 CPU 需要任务时 | "叫号"------从 DSQ 取出 task 送到 CPU |
running |
每次调度执行时 | "开工"------task 即将占用 CPU |
stopping |
每次调度结束时 | "收工"------task 让出 CPU |
quiescent |
每次变为不可运行时 | "离场"------通知 task 变为 quiescent |
set_weight |
权重变更时 | 通知 BPF 调度器 task 的权重 |
set_cpumask |
CPU 亲和性变更时 | 通知允许运行的 CPU 集合 |
2.2 回调分类
一次性回调(每个 task 仅触发一次):
init_task--- 登记,task 被 scx 框架认识enable--- 上岗,task 被 scx 正式接管
状态通知回调(每次状态变化时触发):
runnable/quiescent--- 可运行 / 不可运行running/stopping--- 开始执行 / 停止执行set_weight/set_cpumask--- 权重 / 亲和性变更
调度决策回调(核心调度逻辑):
select_cpu--- 选核决策,选择目标 CPUenqueue--- 入队决策,放入 DSQdispatch--- 分发决策,从 DSQ 取出送到 CPU
3. task 生命周期中的回调时序
#mermaid-svg-CFwM216ATxBiiIGM{font-size:30px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CFwM216ATxBiiIGM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CFwM216ATxBiiIGM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CFwM216ATxBiiIGM .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-CFwM216ATxBiiIGM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CFwM216ATxBiiIGM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CFwM216ATxBiiIGM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CFwM216ATxBiiIGM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CFwM216ATxBiiIGM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CFwM216ATxBiiIGM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CFwM216ATxBiiIGM .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-CFwM216ATxBiiIGM .marker.cross{stroke:#0b0b0b;}#mermaid-svg-CFwM216ATxBiiIGM svg{font-size:30px;}#mermaid-svg-CFwM216ATxBiiIGM p{margin:0;}#mermaid-svg-CFwM216ATxBiiIGM .edge{stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .section--1 rect,#mermaid-svg-CFwM216ATxBiiIGM .section--1 path,#mermaid-svg-CFwM216ATxBiiIGM .section--1 circle,#mermaid-svg-CFwM216ATxBiiIGM .section--1 path{fill:hsl(40.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section--1 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon--1{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge--1{stroke:hsl(40.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth--1{stroke-width:17;}#mermaid-svg-CFwM216ATxBiiIGM .section--1 line{stroke:rgb(0, 52.2500000001, 161.5000000002);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-0 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-0 path,#mermaid-svg-CFwM216ATxBiiIGM .section-0 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-0 path{fill:hsl(-79.4117647059, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-0 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-0{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-0{stroke:hsl(-79.4117647059, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-0{stroke-width:14;}#mermaid-svg-CFwM216ATxBiiIGM .section-0 line{stroke:rgb(52.2500000001, 161.5000000002, 0);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-1 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-1 path,#mermaid-svg-CFwM216ATxBiiIGM .section-1 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-1 path{fill:hsl(220.5882352941, 100%, 73.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-1 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-1{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-1{stroke:hsl(220.5882352941, 100%, 73.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-1{stroke-width:11;}#mermaid-svg-CFwM216ATxBiiIGM .section-1 line{stroke:rgb(136.0000000002, 92.0000000001, 0);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-2 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-2 path,#mermaid-svg-CFwM216ATxBiiIGM .section-2 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-2 path{fill:hsl(70.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-2 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-2{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-2{stroke:hsl(70.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-2{stroke-width:8;}#mermaid-svg-CFwM216ATxBiiIGM .section-2 line{stroke:rgb(28.5, 0, 161.5000000002);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-3 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-3 path,#mermaid-svg-CFwM216ATxBiiIGM .section-3 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-3 path{fill:hsl(100.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-3 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-3{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-3{stroke:hsl(100.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-3{stroke-width:5;}#mermaid-svg-CFwM216ATxBiiIGM .section-3 line{stroke:rgb(109.2500000001, 0, 161.5000000002);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-4 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-4 path,#mermaid-svg-CFwM216ATxBiiIGM .section-4 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-4 path{fill:hsl(130.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-4 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-4{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-4{stroke:hsl(130.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-4{stroke-width:2;}#mermaid-svg-CFwM216ATxBiiIGM .section-4 line{stroke:rgb(161.5000000002, 0, 133.0000000002);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-5 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-5 path,#mermaid-svg-CFwM216ATxBiiIGM .section-5 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-5 path{fill:hsl(160.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-5 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-5{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-5{stroke:hsl(160.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-5{stroke-width:-1;}#mermaid-svg-CFwM216ATxBiiIGM .section-5 line{stroke:rgb(161.5000000002, 0, 52.2500000001);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-6 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-6 path,#mermaid-svg-CFwM216ATxBiiIGM .section-6 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-6 path{fill:hsl(190.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-6 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-6{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-6{stroke:hsl(190.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-6{stroke-width:-4;}#mermaid-svg-CFwM216ATxBiiIGM .section-6 line{stroke:rgb(161.5000000002, 28.5, 0);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-7 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-7 path,#mermaid-svg-CFwM216ATxBiiIGM .section-7 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-7 path{fill:hsl(250.5882352941, 100%, 75%);}#mermaid-svg-CFwM216ATxBiiIGM .section-7 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-7{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-7{stroke:hsl(250.5882352941, 100%, 75%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-7{stroke-width:-7;}#mermaid-svg-CFwM216ATxBiiIGM .section-7 line{stroke:rgb(105, 127.5, 0);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-8 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-8 path,#mermaid-svg-CFwM216ATxBiiIGM .section-8 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-8 path{fill:hsl(310.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-8 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-8{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-8{stroke:hsl(310.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-8{stroke-width:-10;}#mermaid-svg-CFwM216ATxBiiIGM .section-8 line{stroke:rgb(0, 161.5000000002, 28.5);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-9 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-9 path,#mermaid-svg-CFwM216ATxBiiIGM .section-9 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-9 path{fill:hsl(340.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-9 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-9{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-9{stroke:hsl(340.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-9{stroke-width:-13;}#mermaid-svg-CFwM216ATxBiiIGM .section-9 line{stroke:rgb(0, 161.5000000002, 109.2500000001);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-10 rect,#mermaid-svg-CFwM216ATxBiiIGM .section-10 path,#mermaid-svg-CFwM216ATxBiiIGM .section-10 circle,#mermaid-svg-CFwM216ATxBiiIGM .section-10 path{fill:hsl(10.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-10 text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .node-icon-10{font-size:40px;color:#333;}#mermaid-svg-CFwM216ATxBiiIGM .section-edge-10{stroke:hsl(10.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .edge-depth-10{stroke-width:-16;}#mermaid-svg-CFwM216ATxBiiIGM .section-10 line{stroke:rgb(0, 133.0000000002, 161.5000000002);stroke-width:3;}#mermaid-svg-CFwM216ATxBiiIGM .lineWrapper line{stroke:#333;}#mermaid-svg-CFwM216ATxBiiIGM .disabled,#mermaid-svg-CFwM216ATxBiiIGM .disabled circle,#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:lightgray;}#mermaid-svg-CFwM216ATxBiiIGM .disabled text{fill:#efefef;}#mermaid-svg-CFwM216ATxBiiIGM .section-root rect,#mermaid-svg-CFwM216ATxBiiIGM .section-root path,#mermaid-svg-CFwM216ATxBiiIGM .section-root circle{fill:hsl(40.5882352941, 100%, 68.3333333333%);}#mermaid-svg-CFwM216ATxBiiIGM .section-root text{fill:#333;}#mermaid-svg-CFwM216ATxBiiIGM .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-CFwM216ATxBiiIGM .edge{fill:none;}#mermaid-svg-CFwM216ATxBiiIGM .eventWrapper{filter:brightness(120%);}#mermaid-svg-CFwM216ATxBiiIGM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建阶段 init_task 登记进入 scx 框架 enable 被 scx 正式接管 每次唤醒 select_cpu 选择目标 CPU runnable 通知 task 可运行 enqueue 放入调度队列 每次调度 dispatch 从 DSQ 取出 task 送到 CPU running 开始占用 CPU ... 执行任务 ... stopping 让出 CPU 销毁 disable 脱离 scx 管理 task 生命周期中的 scx 回调时序
3.1 一次性回调 vs 重复回调
#mermaid-svg-xJVdp9a6dcbGnv7D{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xJVdp9a6dcbGnv7D .error-icon{fill:#552222;}#mermaid-svg-xJVdp9a6dcbGnv7D .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xJVdp9a6dcbGnv7D .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xJVdp9a6dcbGnv7D .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xJVdp9a6dcbGnv7D .marker.cross{stroke:#333333;}#mermaid-svg-xJVdp9a6dcbGnv7D svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xJVdp9a6dcbGnv7D p{margin:0;}#mermaid-svg-xJVdp9a6dcbGnv7D .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xJVdp9a6dcbGnv7D .cluster-label text{fill:#333;}#mermaid-svg-xJVdp9a6dcbGnv7D .cluster-label span{color:#333;}#mermaid-svg-xJVdp9a6dcbGnv7D .cluster-label span p{background-color:transparent;}#mermaid-svg-xJVdp9a6dcbGnv7D .label text,#mermaid-svg-xJVdp9a6dcbGnv7D span{fill:#333;color:#333;}#mermaid-svg-xJVdp9a6dcbGnv7D .node rect,#mermaid-svg-xJVdp9a6dcbGnv7D .node circle,#mermaid-svg-xJVdp9a6dcbGnv7D .node ellipse,#mermaid-svg-xJVdp9a6dcbGnv7D .node polygon,#mermaid-svg-xJVdp9a6dcbGnv7D .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xJVdp9a6dcbGnv7D .rough-node .label text,#mermaid-svg-xJVdp9a6dcbGnv7D .node .label text,#mermaid-svg-xJVdp9a6dcbGnv7D .image-shape .label,#mermaid-svg-xJVdp9a6dcbGnv7D .icon-shape .label{text-anchor:middle;}#mermaid-svg-xJVdp9a6dcbGnv7D .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xJVdp9a6dcbGnv7D .rough-node .label,#mermaid-svg-xJVdp9a6dcbGnv7D .node .label,#mermaid-svg-xJVdp9a6dcbGnv7D .image-shape .label,#mermaid-svg-xJVdp9a6dcbGnv7D .icon-shape .label{text-align:center;}#mermaid-svg-xJVdp9a6dcbGnv7D .node.clickable{cursor:pointer;}#mermaid-svg-xJVdp9a6dcbGnv7D .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xJVdp9a6dcbGnv7D .arrowheadPath{fill:#333333;}#mermaid-svg-xJVdp9a6dcbGnv7D .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xJVdp9a6dcbGnv7D .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xJVdp9a6dcbGnv7D .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xJVdp9a6dcbGnv7D .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xJVdp9a6dcbGnv7D .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xJVdp9a6dcbGnv7D .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xJVdp9a6dcbGnv7D .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xJVdp9a6dcbGnv7D .cluster text{fill:#333;}#mermaid-svg-xJVdp9a6dcbGnv7D .cluster span{color:#333;}#mermaid-svg-xJVdp9a6dcbGnv7D div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xJVdp9a6dcbGnv7D .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xJVdp9a6dcbGnv7D rect.text{fill:none;stroke-width:0;}#mermaid-svg-xJVdp9a6dcbGnv7D .icon-shape,#mermaid-svg-xJVdp9a6dcbGnv7D .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xJVdp9a6dcbGnv7D .icon-shape p,#mermaid-svg-xJVdp9a6dcbGnv7D .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xJVdp9a6dcbGnv7D .icon-shape .label rect,#mermaid-svg-xJVdp9a6dcbGnv7D .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xJVdp9a6dcbGnv7D .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xJVdp9a6dcbGnv7D .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xJVdp9a6dcbGnv7D :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 仅一次
仅一次
循环
ops.init_task()
ops.enable()
enqueue / dequeue
ops.dispatch()
ops.running()
task 在 CPU 上执行
ops.stopping()
init_task 和 enable 是"一次性门禁",只在 task 进入 scx 管理时各触发一次;而 running 和 stopping 是"旋转门",每次 task 被调度到 CPU 或让出 CPU 时都会触发,构成调度循环。
4. task 的四种状态
每个 task 在 scx 框架中都有一个状态,记录在 task->scx.state 中:
c
// include/linux/sched/ext.h
enum scx_task_state {
SCX_TASK_NONE, // ops.init_task() 还没被调用
SCX_TASK_INIT, // init_task 执行成功,但任务还没就绪
SCX_TASK_READY, // 完全初始化,可以被 scx 调度
SCX_TASK_ENABLED, // 已激活,正在被 scx 调度
SCX_TASK_NR_STATES,
};
状态流转图:
#mermaid-svg-wqfMPiDe99byKUjf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wqfMPiDe99byKUjf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wqfMPiDe99byKUjf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wqfMPiDe99byKUjf .error-icon{fill:#552222;}#mermaid-svg-wqfMPiDe99byKUjf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wqfMPiDe99byKUjf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wqfMPiDe99byKUjf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wqfMPiDe99byKUjf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wqfMPiDe99byKUjf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wqfMPiDe99byKUjf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wqfMPiDe99byKUjf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wqfMPiDe99byKUjf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wqfMPiDe99byKUjf .marker.cross{stroke:#333333;}#mermaid-svg-wqfMPiDe99byKUjf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wqfMPiDe99byKUjf p{margin:0;}#mermaid-svg-wqfMPiDe99byKUjf defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-wqfMPiDe99byKUjf g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-wqfMPiDe99byKUjf g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-wqfMPiDe99byKUjf g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-wqfMPiDe99byKUjf g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-wqfMPiDe99byKUjf g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-wqfMPiDe99byKUjf .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-wqfMPiDe99byKUjf .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-wqfMPiDe99byKUjf .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-wqfMPiDe99byKUjf .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-wqfMPiDe99byKUjf .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-wqfMPiDe99byKUjf .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-wqfMPiDe99byKUjf .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-wqfMPiDe99byKUjf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wqfMPiDe99byKUjf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wqfMPiDe99byKUjf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wqfMPiDe99byKUjf .edgeLabel .label text{fill:#333;}#mermaid-svg-wqfMPiDe99byKUjf .label div .edgeLabel{color:#333;}#mermaid-svg-wqfMPiDe99byKUjf .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-wqfMPiDe99byKUjf .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-wqfMPiDe99byKUjf .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-wqfMPiDe99byKUjf .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-wqfMPiDe99byKUjf .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-wqfMPiDe99byKUjf .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wqfMPiDe99byKUjf .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wqfMPiDe99byKUjf #statediagram-barbEnd{fill:#333333;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wqfMPiDe99byKUjf .cluster-label,#mermaid-svg-wqfMPiDe99byKUjf .nodeLabel{color:#131300;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-wqfMPiDe99byKUjf .note-edge{stroke-dasharray:5;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-note text{fill:black;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram-note .nodeLabel{color:black;}#mermaid-svg-wqfMPiDe99byKUjf .statediagram .edgeLabel{color:red;}#mermaid-svg-wqfMPiDe99byKUjf #dependencyStart,#mermaid-svg-wqfMPiDe99byKUjf #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-wqfMPiDe99byKUjf .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wqfMPiDe99byKUjf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 任务创建
init_task 成功返回
注册时 第一轮遍历
fork时 scx_post_fork
sched_class == ext
switching_to_scx 或 scx_post_fork 中 enable
sched_class != ext,保持 READY
调度器卸载或策略切换
SCX_TASK_NONE
SCX_TASK_INIT
SCX_TASK_READY
SCX_TASK_ENABLED
| 状态 | 含义 |
|---|---|
SCX_TASK_NONE |
初始状态,还未被 scx 认识 |
SCX_TASK_INIT |
短暂中间态,init_task 返回 0 后立即进入 |
SCX_TASK_READY |
完全初始化,可以被 scx 调度 |
SCX_TASK_ENABLED |
激活态,正在被 scx 调度,ops.enable() 已调用 |
SCX_TASK_INIT 是一个中间态,只在 scx_init_task() 执行成功后短暂存在,紧接着就会被推进到 READY。
5. ext_sched_class 全貌
sched_ext 在内核中注册为 ext_sched_class,它是完整的 Linux 调度类(sched_class)。内核核心调度器在调度事件发生时,统一通过 sched_class 的方法指针来调用 scx 的实现。为方便后续各篇分析时对照,这里给出 ext_sched_class 的完整定义(kernel/sched/ext.c:3324):
c
DEFINE_SCHED_CLASS(ext) = {
.enqueue_task = enqueue_task_scx,
.dequeue_task = dequeue_task_scx,
.yield_task = yield_task_scx,
.yield_to_task = yield_to_scx,
.wakeup_preempt = wakeup_preempt_scx,
.balance = balance_scx,
.pick_task = pick_task_scx,
.put_prev_task = put_prev_task_scx, // ← stopping 在这里触发
.set_next_task = set_next_task_scx, // ← running 在这里触发
.select_task_rq = select_task_rq_scx,
.task_woken = task_woken_scx,
.set_cpus_allowed = set_cpus_allowed_scx,
.rq_online = rq_online_scx,
.rq_offline = rq_offline_scx,
.task_tick = task_tick_scx,
.switching_to = switching_to_scx,
.switched_from = switched_from_scx,
.switched_to = switched_to_scx,
.reweight_task = reweight_task_scx,
.prio_changed = prio_changed_scx,
.update_curr = update_curr_scx,
#ifdef CONFIG_UCLAMP_TASK
.uclamp_enabled = 1,
#endif
};
注意两个关键点:
ext_sched_class没有pick_next_task方法 ,只有pick_task。这意味着在__pick_next_task中,scx 走的是class->pick_task(rq)+put_prev_set_next_task()分支,而不是class->pick_next_task(rq, prev)分支。- running 和 stopping 分别挂接在
set_next_task和put_prev_task上 。这两个方法在每次调度切换时成对调用:先put_prev_task(旧任务 stopping),再set_next_task(新任务 running)。
6. 小结与系列导航
本文从宏观角度描绘了 sched_ext 框架的全貌:
- 架构层面 :sched_ext 是一个 eBPF 驱动的调度器插件系统,用户态 BPF 程序通过实现
struct sched_ext_ops中的回调来定义调度策略,内核在关键调度时机调用这些回调。 - 回调体系 :11 个核心回调分为三类------一次性回调(
init_task、enable)、状态通知回调(runnable/quiescent、running/stopping等)和调度决策回调(select_cpu、enqueue、dispatch)。 - 状态机 :task 在 scx 框架中经历
NONE → INIT → READY → ENABLED四个状态,其中INIT是短暂中间态,ENABLED是正常运行态。 - 调度类集成 :
ext_sched_class作为标准的 Linuxsched_class注册到内核,核心调度器通过统一接口调用 scx 的实现。
理解了框架全貌之后,后续文章将逐一深入每个回调的内核实现细节。建议按以下顺序阅读:
- init_task ------ 每个 task 走进调度器的第一道门,理解 task 如何被 scx 框架"登记"
- enable ------ task 被 scx 正式接管的关键时刻,理解状态从 READY 到 ENABLED 的跃迁
- select_cpu ------ 任务唤醒时的选核决策,理解 BPF 调度器如何影响 CPU 选择
- runnable ------ 任务状态转换的哨兵,理解 runnable/quiescent 的对称设计
- enqueue ------ 任务入队,理解 DSQ 机制和调度决策的核心逻辑
- dispatch ------ 从 DSQ 取出任务送到 CPU,理解分发机制的完整流程
- running ------ 任务开始执行,理解 running/stopping 的成对设计