温馨提示×

Linux 进程如何调度

小樊
42
2026-08-31 10:02:46
栏目: 智能运维

Linux 的进程调度是一个分层、可扩展、基于调度类(scheduler class) 的体系,核心思想可以概括为:按调度类优先级选择 → 在选中的调度类里按策略选进程 → 根据时间片或事件触发切换。下面从整体架构 → 调度类与策略 → 调度流程 → 关键机制 → 常见调度器演变系统说明。


一、整体调度架构(核心思想)

Linux 调度器不是“一个算法”,而是 调度类 + 调度策略 的组合:

调度器核心
 ├── 调度类(sched_class)按优先级排列
 │    ├── stop_sched_class        (最高,用于 CPU 停止)
 │    ├── dl_sched_class          (Deadline)
 │    ├── rt_sched_class          (实时)
 │    ├── fair_sched_class        (CFS,普通进程)
 │    └── idle_sched_class        (idle)
 └── 每个调度类有自己的一套调度策略

调度时:

  1. 先比调度类优先级
  2. 再在调度类内部选进程

二、调度类与调度策略

1️⃣ 调度类(Scheduler Class)

调度类 用途
stop 内核紧急任务(迁移、停 CPU)
dl Deadline 调度(实时)
rt 实时进程(RT)
fair 普通进程(CFS,最常见)
idle 空闲任务

2️⃣ 调度策略(policy)

✅ 普通进程(CFS)

SCHED_OTHER / SCHED_NORMAL
  • 完全公平调度器(Completely Fair Scheduler)
  • 虚拟运行时间 vruntime 调度
  • 动态时间片

✅ 实时进程(RT)

SCHED_FIFO
SCHED_RR
  • 优先级 1–99
  • 实时类 高于普通进程
  • FIFO:不主动让出就一直运行
  • RR:有时间片轮转

✅ Deadline

SCHED_DEADLINE
  • 基于 任务截止时间
  • 用于强实时系统

三、CFS(普通进程)调度原理(重点)

1️⃣ 核心思想

让每个进程“看起来”都在公平地使用 CPU

CFS 不维护固定时间片,而是维护 vruntime(虚拟运行时间)


2️⃣ vruntime(虚拟运行时间)

vruntime += 实际运行时间 × (NICE_0_LOAD / 进程权重)
  • 高优先级(nice 小) → 权重高 → vruntime 增长慢
  • 低优先级(nice 大) → 权重低 → vruntime 增长快

总是选择 vruntime 最小的进程运行


3️⃣ 红黑树(rbtree)

  • 所有可运行进程按 vruntime 放入红黑树
  • 最左节点 = 下一个要运行的进程
  • 插入 / 删除 / 查找:O(log n)

4️⃣ 时间片

  • 没有固定时间片
  • 调度周期(sched_latency) 和进程数量动态计算
  • 保证调度延迟可控

四、调度触发时机

1️⃣ 触发调度的情况

  • 进程 时间片用完
  • 进程 主动让出 CPU
    schedule()
    
  • 进程 阻塞(sleep / IO)
  • 进程 被唤醒
  • 创建新进程
  • 中断返回用户态

2️⃣ 抢占(Preemption)

用户抢占

  • 系统调用返回
  • 中断返回

内核抢占(CONFIG_PREEMPT)

  • 内核代码某些点可抢占
  • 提高实时性

五、调度流程(简化)

tick 中断 / 事件
   ↓
schedule()
   ↓
pick_next_task()
   ↓
遍历调度类
   ↓
选定进程
   ↓
context_switch()

六、进程优先级与 nice 值

1️⃣ nice 值(-20 ~ 19)

nice -n 10 ./app
renice -n -5 -p PID
  • nice 越小 → 优先级越高
  • 只影响 CFS

2️⃣ 实时优先级(1–99)

chrt -f 10 ./app
  • 高于普通进程
  • 永远优先于 CFS

七、调度器相关系统调用

函数 作用
sched_setscheduler() 设置调度策略
sched_getparam() 获取调度参数
sched_yield() 主动让出 CPU
setpriority() 设置优先级

八、调度器演变(历史)

版本 调度器
2.4 O(n)
2.6 早期 O(1)
2.6.23+ CFS(至今)

九、一个经典比喻

CFS 就像一个公平的裁判
每个人跑得时间不同,但裁判保证“谁跑得少,就让谁先跑”。


十、总结一句话

Linux 调度 = 调度类优先级 + 调度策略 + vruntime 公平 + 事件驱动抢占

如果你愿意,我可以:

  • 画一张 调度流程图
  • 代码级视角schedule()
  • 对比 RT vs CFS vs Deadline
  • 结合 多核 / NUMA / cgroup CPU 讲调度

你更想深入哪一块?

0