Linux 进程调度器全景:CFS、实时调度类与调度策略对比

在深入 Nginx 吞吐量调优之前,必须理解 Linux 进程调度器的完整架构。调度器决定了 CPU 时间如何在多个进程之间分配,直接影响 Nginx 这类网络密集型服务的响应延迟与并发处理能力。本章从调度器整体框架出发,对比 CFS、实时调度类以及三种核心调度策略(SCHED_OTHER、SCHED_FIFO、SCHED_RR),为后续参数调优奠定理论基础。

调度器整体架构

Linux 内核采用模块化调度框架,核心调度代码(kernel/sched/core.c)通过统一接口调用不同的调度类。每个调度类实现自己的就绪队列与调度算法,内核根据进程的调度策略选择对应的调度类。

核心调度类层次:
  • stop_sched_class — 最高优先级,用于停止 CPU 等特殊任务
  • dl_sched_class — Deadline 调度类,用于实时截止期限任务
  • rt_sched_class — 实时调度类,支持 SCHED_FIFO 和 SCHED_RR
  • fair_sched_class — 完全公平调度类(CFS),对应 SCHED_OTHER、SCHED_BATCH、SCHED_IDLE
  • idle_sched_class — 空闲调度类,CPU 无任务时运行
Linux 调度器架构全景 Linux 调度器架构全景 核心调度器 (core.c) 调度类选择器(根据 policy 选择对应调度类) stop_sched_class 最高优先级 dl_sched_class Deadline 调度 rt_sched_class SCHED_FIFO/RR fair_sched_class CFS (SCHED_OTHER) idle_sched_class 空闲任务 调度策略与调度类的映射关系 SCHED_OTHER → fair_sched_class | SCHED_FIFO/SCHED_RR → rt_sched_class | SCHED_DEADLINE → dl_sched_class stop 队列 dl_rq rt_rq cfs_rq (红黑树) idle 队列

完全公平调度器(CFS)

CFS 是 Linux 默认调度器,对应 SCHED_OTHER 策略。其核心设计理念是“理想公平”:假设存在一个完全公平的多任务 CPU,每个任务获得 1/n 的 CPU 时间。CFS 通过虚拟运行时间(vruntime)实现这一目标。

CFS 核心概念 说明
vruntime 虚拟运行时间,记录进程实际消耗的 CPU 时间(经优先级加权)。CFS 总是选择 vruntime 最小的进程运行。
红黑树 就绪队列以 vruntime 为键值组织成红黑树,最左节点即 vruntime 最小的进程。
调度延迟 保证每个可运行进程在给定时间窗口内至少获得一次 CPU 时间。
时间片 CFS 没有固定时间片,而是根据可运行进程数量动态计算:时间片 = 调度延迟 / 进程数。
nice 值 权重因子,范围 -20~19,值越小权重越高,vruntime 增长越慢,获得更多 CPU 时间。
调优要点: Nginx 工作进程通常使用 SCHED_OTHER 策略。通过调整 sched_latency_ns(调度延迟)和 min_granularity_ns(最小粒度),可以控制 Nginx 进程的时间片大小,影响吞吐量与延迟的平衡。
CFS 红黑树调度示意图 CFS 红黑树调度示意图 vruntime=100 vruntime=80 vruntime=130 vruntime=60 vruntime=95 ← 选中运行 CFS 始终选择红黑树最左节点(vruntime 最小)作为下一个运行进程

实时调度类(RT)

实时调度类用于对响应时间有严格要求的任务,支持两种调度策略:SCHED_FIFO 和 SCHED_RR。实时进程的优先级范围是 0~99(数值越大优先级越高),始终高于普通进程(nice 值映射到 100~139 优先级)。

SCHED_FIFO(先进先出)

  • 没有时间片限制,一旦获得 CPU,除非主动让出(如 sleep、等待 I/O)或被更高优先级进程抢占,否则一直运行。
  • 适用于需要极低延迟且执行时间短的任务,如中断处理线程。
  • 风险: 如果 FIFO 进程进入死循环,会永久阻塞所有低优先级进程,包括系统关键服务。

SCHED_RR(轮转)

  • 在 FIFO 基础上增加了时间片轮转机制。同一优先级的 RR 进程按时间片轮流执行。
  • 时间片长度由内核参数 sched_rr_timeslice_ms 控制(默认 100ms)。
  • 适用于需要公平轮转的实时任务,如多媒体处理。
Nginx 调优警告: 不建议将 Nginx 工作进程设置为 SCHED_FIFO 或 SCHED_RR。实时策略可能使 Nginx 长时间占用 CPU,导致其他系统服务(如 SSH、监控代理)无响应。仅在隔离的专用服务器上,且经过充分测试后,才可考虑将 Nginx 关键线程提升为实时优先级。

三种调度策略对比

特性 SCHED_OTHER (CFS) SCHED_FIFO SCHED_RR
调度类 fair_sched_class rt_sched_class rt_sched_class
优先级范围 100~139(nice -20~19) 0~99 0~99
时间片 动态计算(基于调度延迟和进程数) 无时间片(运行直到主动让出) 固定时间片(默认 100ms)
抢占条件 更高优先级进程就绪,或 vruntime 差值超过阈值 更高优先级 FIFO/RR 进程就绪 更高优先级进程就绪,或时间片耗尽
适用场景 通用服务器、Web 服务、数据库 硬实时、中断处理、低延迟控制 软实时、多媒体、周期性任务
对 Nginx 的适用性 ✅ 默认推荐,公平且稳定 ⚠️ 高风险,仅特殊场景 ⚠️ 中等风险,需严格测试
三种调度策略执行模型对比 三种调度策略执行模型对比 SCHED_OTHER (CFS) P1 P2 P1 P3 P2 时间片动态分配,公平共享 CPU SCHED_FIFO P1(高优先级)持续运行 P2 等待 P1 不主动让出,P2 永远无法运行 SCHED_RR P1 P2 P1 P2 固定时间片轮转,同优先级公平 调度策略选择建议 • Nginx 工作进程 → SCHED_OTHER(默认),通过调整 CFS 参数优化吞吐量 • 专用 Nginx 服务器可将 accept 线程设为 SCHED_FIFO(优先级 1~10) • 实时策略必须配合 CPU 亲和性和 cgroup 限制,防止系统锁死

调度策略的查看与设置

在 Linux 系统中,可以使用 chrt 命令查看和修改进程的调度策略与优先级。

# 查看 Nginx 工作进程的调度策略
chrt -p $(pgrep -f 'nginx: worker')

# 将 Nginx 工作进程设置为 SCHED_FIFO,优先级 10
chrt -f -p 10 $(pgrep -f 'nginx: worker')

# 将 Nginx 工作进程设置为 SCHED_RR,优先级 10
chrt -r -p 10 $(pgrep -f 'nginx: worker')

# 查看所有进程的调度策略
ps -eo pid,comm,policy,rtprio,ni | grep nginx
关键输出字段说明:
  • policy — 调度策略标识:TS(SCHED_OTHER)、FF(SCHED_FIFO)、RR(SCHED_RR)
  • rtprio — 实时优先级(仅对 FF/RR 有效)
  • ni — nice 值(仅对 TS 有效)

调度器参数对 Nginx 的影响路径

理解调度器全景后,需要明确调度参数如何最终影响 Nginx 的吞吐量:

  1. CFS 调度延迟(sched_latency_ns) — 增大该值使每个 Nginx 工作进程获得更长的时间片,减少上下文切换次数,提升吞吐量;但会增加其他进程的调度延迟。
  2. 最小粒度(min_granularity_ns) — 控制进程被抢占的最小执行时间。减小该值使调度更频繁,提升交互性但降低吞吐量。
  3. nice 值 — 降低 Nginx 进程的 nice 值(提高优先级),使其在竞争 CPU 时获得更多时间片。
  4. 实时优先级 — 将 Nginx 关键线程提升为实时优先级,可显著降低延迟,但必须谨慎使用。
调度参数影响 Nginx 吞吐量路径 调度参数影响 Nginx 吞吐量路径 sched_latency_ns 调度延迟 min_granularity_ns 最小粒度 nice 值 / 实时优先级 进程优先级 时间片大小 上下文切换频率 Nginx 吞吐量 请求/秒 · 延迟分布 时间片越大 → 上下文切换越少 → 吞吐量越高 但延迟公平性下降,需根据业务场景权衡

小结

Linux 调度器通过模块化架构将 CFS、实时调度类和空闲调度类有机整合。对于 Nginx 调优而言,SCHED_OTHER(CFS) 是默认且最安全的选择,通过调整 CFS 内核参数(调度延迟、最小粒度)和进程 nice 值,可以在吞吐量与延迟之间找到最佳平衡点。实时调度策略(SCHED_FIFO/SCHED_RR)虽然能提供极低延迟,但风险较高,仅在充分隔离的环境中谨慎使用。

下一阶段准备: 在掌握调度器全景后,第 3 章将深入 CFS 的关键内核参数(sched_latency_ns、min_granularity_ns、sched_nr_latency),通过实验数据展示这些参数如何具体影响 Nginx 的吞吐量曲线。