Skip to content

第五十五章:结丹圆满

结丹圆满

涉及内核源码:

林小源站在调度竞技场的中央,回望来时的路。

从 CFS 的红黑树到 RT 的优先级队列,从 Deadline 的时间契约到 idle 的低功耗等待,从上下文切换的寄存器手术到负载均衡的多核博弈——他走过了调度器的完整路径。

竞技场上空,五位调度类的守关人并肩而立。stop 的身影依然模糊,Deadline 的金色长袍在风中飘动,RT 的银色铠甲反射着光芒,CFS 的绿色长衫温文尔雅,idle 少年靠在柱子上打着哈欠。

"你已经走了很远。"CFS 从空中落下,站在林小源面前。

林小源抱拳行礼:"多谢前辈一路指引。"

CFS 摇摇头:"不是我指引你,是你自己走过来的。调度器的每一个环节——vruntime、红黑树、时间片、唤醒抢占、上下文切换、负载均衡——你都亲眼看过、亲手摸过。现在,你理解了吗?"

林小源沉默了片刻,然后说:"我理解了调度器的机制,但更重要的是,我理解了调度器的哲学。"

林小源走到竞技场的边缘,坐在一块石头上。

调度仙子从远处走来,在他身边坐下。她的长裙上绣着调度器的所有数据结构——rq、sched_entity、cfs_rq、sched_class——每一个都在微微发光。

"你学到了什么?"她问。

林小源看着竞技场上的进程们,说:"公平不是平均。CFS 的公平是按权重分配——权重高的进程获得更多 CPU 时间,权重低的进程获得更少。这不是平均主义,而是按需分配。"

调度仙子点头:"继续。"

"选择取决于需求。CFS 适合普通进程,RT 适合实时任务,Deadline 适合硬实时任务。没有'最好'的调度器,只有'最合适'的调度器。每种调度器都有自己的适用场景,它们是互补的,不是替代的。"

"还有呢?"

"权衡是永恒的主题。延迟和吞吐量、缓存亲和性和负载均衡、性能和能效——每一个优化都有代价,每一个选择都有权衡。调度器的目标不是让每个因素都最优,而是让整体效果最好。"

调度仙子微笑着站起身来:"你已经准备好了。"

林小源站起身来,感受到了一股力量从丹田涌起。

那是结丹圆满的力量——他对调度器的理解已经达到了一个临界点。从 ,从 CFS 红黑树到 RT 调度器,从上下文切换到负载均衡——每一个环节都清晰地呈现在他眼前。

"结丹圆满。"他低声说。

但这只是开始。调度器只是内核的一个子系统。内存管理、文件系统、网络栈、设备驱动——还有无数的领域等待他去探索。

他抬头望向内核的深处。那里有更复杂的机制、更精妙的设计、更深邃的哲理。他还没有遇到内存长老、VFS 阁主、网络真人——那些传说中的存在。

但他已经准备好了。

idle 少年从柱子旁走来,拍了拍他的肩膀:"别忘了我。当你在其他子系统中遇到困难时,回来找我。idle 永远在这里。"

林小源笑了:"谢谢你,idle 前辈。"

他转身走向内核的深处,脚步坚定而从容。身后,调度竞技场渐渐远去,但那些教训——公平、效率、权衡、选择——将永远伴随着他。

天道均衡,亦酬进取。


c
/*
 * 调度器的完整图景:
 *
 * 核心函数:
 *   schedule()           — 调度入口
 *   pick_next_task()     — 选择下一个进程
 *   context_switch()     — 上下文切换
 *   scheduler_tick()     — 时钟中断处理
 *   try_to_wake_up()     — 唤醒进程
 *   select_task_rq()     — 选择目标 CPU
 *   load_balance()       — 负载均衡
 *
 * 调度类:
 *   stop > dl > rt > fair > idle
 *
 * 数据结构:
 *   struct rq            — per-CPU 运行队列
 *   struct sched_entity  — 调度实体
 *   struct cfs_rq        — CFS 运行队列
 *   struct sched_class   — 调度类
 *
 * 关键概念:
 *   vruntime             — 虚拟运行时间
 *   nice / prio          — 优先级
 *   时间片               — 按权重分配
 *   唤醒抢占             — 降低延迟
 *   负载均衡             — 多核公平
 */

struct sched_summary {
    const char *concept;
    const char *key_point;
};

printf("=== 调度器全貌 ===\n\n");

struct sched_summary items[] = {
    { "CFS 调度器",     "vruntime + 红黑树,按权重分配 CPU 时间" },
    { "RT 调度器",      "FIFO/RR,实时优先级 1-99" },
    { "Deadline 调度器", "runtime/deadline/period,时间保证" },
    { "上下文切换",     "保存/恢复寄存器 + 切换页表 + TLB" },
    { "负载均衡",       "per-CPU 运行队列 + 调度域层次" },
    { "唤醒抢占",       "醒来进程可以抢占当前进程" },
    { "调度类",         "多态设计,stop > dl > rt > fair > idle" },
    { "睡眠与唤醒",     "TASK_INTERRUPTIBLE / TASK_UNINTERRUPTIBLE" },
    { "idle 进程",      "最后选择,HLT/WFI 节能" },
    { "内核抢占",       "preempt_count 控制抢占深度" },
};
int nr = sizeof(items) / sizeof(items[0]);

printf("%-16s %s\n", "概念", "关键点");
printf("%-16s %s\n", "---", "---");
for (int i = 0; i < nr; i++) {
    printf("%-16s %s\n", items[i].concept, items[i].key_point);
}

printf("\n--- 调度器的设计哲学 ---\n");
printf("公平: CFS 保证每个进程按权重获得 CPU 时间\n");
printf("效率: per-CPU 运行队列 + O(log n) 红黑树\n");
printf("响应: 唤醒抢占 + 内核抢占\n");
printf("可扩展: 调度类多态设计 + 调度域层次\n");

道藏笔记

内核启示

调度器是 Linux 内核的核心子系统之一。

本卷覆盖的核心概念:

CFS 调度器:

  • vruntime + 红黑树
  • 按权重分配 CPU 时间
  • 唤醒抢占降低延迟

RT 调度器:

  • FIFO/RR 两种策略
  • 实时优先级 1-99
  • 总是优先于 CFS

Deadline 调度器:

  • runtime/deadline/period
  • 截止时间保证
  • 可调度性测试

调度器的基础设施:

  • per-CPU 运行队列
  • 调度类多态设计
  • 上下文切换
  • 负载均衡
  • 睡眠与唤醒

结丹圆满,方可窥见更深的内核之道。


破关试炼

结丹圆满之试

本卷收束时回到调度器根本问题:每次调度最终要调用哪个函数选出下一任务?

答对后才能继续滑动和进入下一章。

以修仙之名,悟内核之道