温馨提示×

linux进程调度如何工作

小樊
39
2026-09-18 15:24:49
栏目: 智能运维

Linux 的进程调度(Process Scheduling)决定了哪个进程在什么时间、使用哪个 CPU 运行,目标是:

  • 公平地分配 CPU 时间
  • 保证交互式任务响应快
  • 提高系统吞吐量和 CPU 利用率
  • 支持实时任务(RT)需求

下面从 整体架构 → 调度类 → 调度策略 → 调度时机 → CFS 原理 → 实时调度 → 多核 逐步说明。


一、Linux 调度整体架构

Linux 调度是**分层 + 调度类(scheduler class)**的设计:

任务
 └─ 调度类(scheduler class)
     ├─ stop_sched_class      (最高优先级,用于 CPU 停止)
     ├─ dl_sched_class        (SCHED_DEADLINE)
     ├─ rt_sched_class        (SCHED_FIFO / SCHED_RR)
     ├─ fair_sched_class      (SCHED_NORMAL / SCHED_BATCH,CFS)
     └─ idle_sched_class      (空闲任务)

调度器按优先级从高到低选择调度类:

高优先级调度类有任务 → 绝不会跑低优先级调度类


二、常见的调度策略(policy)

用户态通过 sched_setscheduler() 设置:

调度类 策略 说明
实时 SCHED_FIFO 先进先出,无时间片
实时 SCHED_RR 时间片轮转
普通 SCHED_NORMAL 普通进程(CFS)
普通 SCHED_BATCH 批处理,少交互
普通 SCHED_IDLE 极低优先级
deadline SCHED_DEADLINE 硬实时,基于截止时间

三、调度时机(什么时候发生调度)

1. 主动调度

  • 进程主动调用 schedule()
  • 例如:sleep()wait()、IO 阻塞

2. 抢占调度

  • 时钟中断(tick
  • 更高优先级任务就绪
  • 当前任务时间片用完(CFS 中叫“虚拟时间”)

3. 唤醒抢占

  • 一个高优先级进程被唤醒
  • 可能立即抢占当前进程

四、CFS(完全公平调度器,核心)

SCHED_NORMAL 使用 CFS(Completely Fair Scheduler)

核心思想

让所有进程“公平”地消耗 CPU 时间

关键概念

1. 虚拟运行时间(vruntime)

  • 每个进程维护一个 vruntime
  • 实际运行时间 ÷ 权重(nice 值)
  • 权重越高,vruntime 增长越慢

2. 红黑树(rbtree)

  • 所有可运行进程按 vruntime 排序
  • 最左节点 = 最该运行的进程

3. 调度过程

调度时:
1. 选红黑树最左节点
2. 运行该进程
3. 更新 vruntime
4. 时间片用尽或抢占 → 重新调度

五、nice 值 & 优先级

  • nice 范围:-20 ~ 19
  • 默认:0
  • nice 越小 → 优先级越高 → 权重越大
nice -n -10 ./app
renice -n 5 -p 1234

六、实时调度(RT)

SCHED_FIFO

  • 优先级 1–99
  • 不自动让出 CPU
  • 只有:
    • 阻塞
    • 被更高优先级抢占
    • 主动 yield

SCHED_RR

  • 类似 FIFO
  • 有固定时间片

⚠️ 实时进程优先级 高于所有普通进程


七、SCHED_DEADLINE(硬实时)

基于 EAR(Earliest Deadline First)

参数:

runtime  // 运行时间
deadline // 截止时间
period   // 周期

适用于:

  • 音视频
  • 控制系统
  • 低延迟交易

八、多核 & CPU 亲和性

  • 每个 CPU 有独立运行队列(runqueue)
  • 支持:
    • 负载均衡(load balance)
    • CPU 亲和性(taskset
taskset -c 0,1 ./app

九、查看调度信息

ps -eo pid,comm,pri,ni,stat,rtprio
top
htop
cat /proc/<pid>/sched

十、一句话总结

Linux 进程调度通过分层调度类 + CFS 公平调度 + 实时调度支持,在公平性和实时性之间取得平衡,由时钟中断、阻塞和唤醒触发调度。

如果你愿意,我可以进一步讲:

  • CFS 源码级流程
  • 为什么 CFS 不用时间片
  • 实时系统如何调优
  • 容器(Docker)里的调度行为

0