Linux 调度策略有多个, 那 cpu 轮转的时候具体选择哪个策略呢?

Linux 支持多种调度策略(如 SCHED_OTHER、SCHED_FIFO、SCHED_RR、SCHED_DEADLINE),那 CPU 轮转(调度)时,内核是如何选择用哪个策略的?

1. 调度器的“分层”选择机制

Linux 调度器采用分层优先级的方式来管理不同策略的进程:

A. 实时优先,普通次之

  1. 实时进程(SCHED_FIFO、SCHED_RR、SCHED_DEADLINE)

    • 优先级最高。只要有可运行的实时进程,调度器一定优先调度实时进程
    • 多个实时进程之间,再根据各自的策略和优先级排序。
  2. 普通进程(SCHED_OTHER、SCHED_BATCH、SCHED_IDLE)

    • 只有在没有可运行的实时进程时,调度器才会选择普通进程。
    • 普通进程之间再用 CFS(完全公平调度器)等算法排序。

2. 调度器的选择流程(简化版)

每当需要调度(比如时间片用完、进程阻塞/唤醒、系统调用等),调度器会:

  1. 检查所有可运行的实时进程队列

    • 如果有 SCHED_DEADLINE 进程,先选 deadline 最早的。
    • 否则,检查 SCHED_FIFO/SCHED_RR 队列,按优先级(1~99)从高到低选择。
    • SCHED_FIFO:同优先级下先到先服务,直到主动让出 CPU。
    • SCHED_RR:同优先级下轮流分配时间片。
  2. 如果没有可运行的实时进程

    • 选择普通进程队列(CFS),按 vruntime(虚拟运行时间)最小的进程调度。
    • SCHED_BATCH、SCHED_IDLE 进程优先级更低,只有系统空闲时才会被调度。

3. 多核系统的情况

  • 每个 CPU 都有自己的就绪队列,但调度器的选择逻辑是一样的。
  • 进程可以在不同 CPU 之间迁移,调度器会做负载均衡。

4. 源码入口

  • 主要在 kernel/sched/core.cpick_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)的进程。每种策略内部再按各自规则排序。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容