Linux 支持多种调度策略(如 SCHED_OTHER、SCHED_FIFO、SCHED_RR、SCHED_DEADLINE),那 CPU 轮转(调度)时,内核是如何选择用哪个策略的?
1. 调度器的“分层”选择机制
Linux 调度器采用分层优先级的方式来管理不同策略的进程:
A. 实时优先,普通次之
-
实时进程(SCHED_FIFO、SCHED_RR、SCHED_DEADLINE)
- 优先级最高。只要有可运行的实时进程,调度器一定优先调度实时进程。
- 多个实时进程之间,再根据各自的策略和优先级排序。
-
普通进程(SCHED_OTHER、SCHED_BATCH、SCHED_IDLE)
- 只有在没有可运行的实时进程时,调度器才会选择普通进程。
- 普通进程之间再用 CFS(完全公平调度器)等算法排序。
2. 调度器的选择流程(简化版)
每当需要调度(比如时间片用完、进程阻塞/唤醒、系统调用等),调度器会:
-
检查所有可运行的实时进程队列
- 如果有 SCHED_DEADLINE 进程,先选 deadline 最早的。
- 否则,检查 SCHED_FIFO/SCHED_RR 队列,按优先级(1~99)从高到低选择。
- SCHED_FIFO:同优先级下先到先服务,直到主动让出 CPU。
- SCHED_RR:同优先级下轮流分配时间片。
-
如果没有可运行的实时进程
- 选择普通进程队列(CFS),按 vruntime(虚拟运行时间)最小的进程调度。
- SCHED_BATCH、SCHED_IDLE 进程优先级更低,只有系统空闲时才会被调度。
3. 多核系统的情况
- 每个 CPU 都有自己的就绪队列,但调度器的选择逻辑是一样的。
- 进程可以在不同 CPU 之间迁移,调度器会做负载均衡。
4. 源码入口
- 主要在
kernel/sched/core.c的pick_next_task()函数。 - 伪代码逻辑如下:
if (有可运行的 SCHED_DEADLINE 进程)
选 deadline 最早的
else if (有可运行的 SCHED_FIFO/SCHED_RR 进程)
选优先级最高的实时进程
else
选 CFS 队列中 vruntime 最小的普通进程
5. 总结
CPU 轮转时,Linux 调度器总是优先选择实时策略(SCHED_DEADLINE > SCHED_FIFO/RR)的进程。如果没有实时进程,才会选择普通策略(SCHED_OTHER/CFS)的进程。每种策略内部再按各自规则排序。