土法炼钢兴趣小组的算法知识备份

【操作系统百科】SCHED_FIFO/RR 与 PREEMPT_RT

文章导航

分类入口
os
标签入口
#sched-fifo#sched-rr#preempt-rt#rt-throttle#priority-inheritance#cyclictest

目录

Linux 不是硬实时 OS,但通过 SCHED_FIFO/RR + PREEMPT_RT 补丁(6.12 主线合入),它在音视频、工业、机器人、金融交易等场景里占据了一席之地。本文讲”把 Linux 变实时”的三层:policy、抢占模型、RT 补丁。

一、先看图:三层抢占模型

flowchart TB
    subgraph PreemptNone[PREEMPT_NONE]
      N1[内核态全部不可抢占]
      N2[延迟可达 100+ms]
    end
    subgraph PreemptVoluntary[PREEMPT_VOLUNTARY]
      V1[cond_resched 点可抢]
      V2[延迟 10-50ms]
    end
    subgraph PreemptNormal[PREEMPT]
      P1[大部分内核可抢]
      P2[延迟 1-5ms]
    end
    subgraph PreemptRT[PREEMPT_RT]
      R1[几乎全可抢]
      R2[spinlock → rt_mutex]
      R3[IRQ → threaded]
      R4[延迟 μs 级]
    end
    PreemptNone --> PreemptVoluntary --> PreemptNormal --> PreemptRT
    classDef low fill:#f8514922,stroke:#f85149,color:#adbac7;
    classDef mid fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    classDef hi fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    class N1,N2 low
    class V1,V2 mid
    class P1,P2,R1,R2,R3,R4 hi

二、实时调度 policy

2.1 SCHED_FIFO

典型:chrt -f 50 ./worker

危险:一个 while(1) 的 FIFO 任务会永占 CPU,把同级以下全饿。必须有 RT-throttling(见第 5 节)或 watchdog。

2.2 SCHED_RR

SCHED_RR 比 FIFO 略安全(至少同级间会让),但对跨级仍有独占问题。

2.3 优先级层次

SCHED_DEADLINE (最先)
SCHED_FIFO/RR  prio 99..1
SCHED_NORMAL (EEVDF)
SCHED_BATCH
SCHED_IDLE

DEADLINE 高于所有 RT;RT 高于 NORMAL。

2.4 RLIMIT_RTPRIO、RLIMIT_RTTIME

普通用户默认不能用 SCHED_FIFO。需要 CAP_SYS_NICE 或调 ulimit -r + /etc/security/limits.conf

RLIMIT_RTTIME 限 RT 任务连续运行时间(μs),超限降级成 SCHED_OTHER 或收 SIGXCPU。防失控。

三、cyclictest:RT 基线

测量”从 hrtimer 到用户态被唤醒”的实际延迟。

cyclictest -p 80 -t 4 -D 1h -i 200 -m

输出 min/avg/max 延迟(μs)。

典型结果:

系统 avg max
通用服务器 PREEMPT 15 μs 300+ μs
PREEMPT + isolcpus + nohz_full 5 μs 50 μs
PREEMPT_RT 调优 3 μs 20 μs
高端嵌入式 + PREEMPT_RT 2 μs 10 μs

max 是关键——硬实时看 worst case,不是平均。

四、PREEMPT_RT:补丁集 20 年历史

2004 Ingo Molnár 起的补丁集,目标:把内核抢占点减到最少。改造点:

  1. spinlock → rt_mutex(大部分):spinlock_t 能睡 + 继承优先级
  2. raw_spinlock_t:真正的自旋,少数必须不能睡的场景
  3. IRQ handler 线程化IRQF_NO_THREAD 外默认跑在内核线程里,可抢
  4. softirq 线程化ksoftirqd/N 运行 softirq;RT 任务可抢它
  5. printk 异步化:不在 IRQ 上下文同步写 console

2023 年开始逐步合入主线;6.12(2024 Q4)宣告 “upstream merge 完成”。

4.1 代价

建议:只对有硬实时需求的系统开 PREEMPT_RT。通用服务器不需要。

4.2 rt_mutex 与优先级继承

经典优先级反转场景:L 持锁 → H 等锁 → M 抢 CPU → L 跑不了 → H 更等不到。

rt_mutex 的 PI:H 等锁时,L 临时升到 H 的优先级直到释放。Linux 中断链接起来,PI 可级联。

PI 在用户态也有:PTHREAD_PRIO_INHERIT。futex2 / FUTEX_PI 是内核支持。

五、RT-throttling:防失控 FIFO

内核默认 /proc/sys/kernel/sched_rt_period_us = 1000000(1 s)和 sched_rt_runtime_us = 950000(0.95 s)——每秒 RT 任务最多跑 0.95 秒,剩余 0.05 秒给 SCHED_OTHER。

while(1) FIFO 锁死系统;但在严肃 RT 系统里常把 runtime 设 -1(无限制),因为你自己得保证 RT 任务短。

六、RT 系统调优清单

  1. Isolate CPUisolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3,让某些核不跑 housekeeping
  2. 禁用 SMT:减少 cache 抖
  3. 绑 IRQ:把无关 IRQ 绑到 housekeeping CPU
  4. 禁用 C-states 深度intel_idle.max_cstate=1——换延迟换能耗
  5. 关 TurboBoost / P-state:频率稳定
  6. 内存预分配 / mlockall:避免 page fault 延迟
  7. huge page:减 TLB miss
  8. PREEMPT_RT 内核:如果 max 要求 < 50μs

这些在工业 PLC、机器人控制、专业音频(JACK)、HFT 交易系统里都是标配。

七、用户态配合

struct sched_param sp = { .sched_priority = 80 };
sched_setscheduler(0, SCHED_FIFO, &sp);

mlockall(MCL_CURRENT | MCL_FUTURE);  // 防被换出

八、常见 RT bug

bug A:FIFO 任务永 spin,整台机死 原因:没 RT-throttling 或 RTTIME 解决:throttling 配置、应用代码加主动 yield

bug B:cyclictest max spike 1ms+ 原因:SMI(System Management Interrupt)、NMI、CPU 频率切换 诊断hwlatdetect 工具

bug C:PREEMPT_RT 编译后网络驱动不稳 原因:某些驱动假设 spinlock 不睡,被 rt_mutex 改后触发 bug 解决:换更新的驱动;这是 RT 在上游完整合入前长期痛点

bug D:优先级反转仍现 原因:锁不是 rt_mutex(某些用户态 lock 没 PI) 解决:pthread mutex + PTHREAD_PRIO_INHERIT

九、小结

下一篇 C-23 讲 SCHED_DEADLINE——EDF+CBS 在内核的落地,以及为什么它是”保量调度”的正确姿势。


参考文献

工具


上一篇EEVDF 下一篇SCHED_DEADLINE:EDF+CBS 的落地

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-01 · os

【操作系统百科】优先级反转与继承

火星探路者号因优先级反转重启——这是实时系统最经典的故事。本文讲优先级反转现象、PIP 优先级继承协议、PCP 优先级天花板、rt_mutex、PREEMPT_RT 的 spinlock 转换、DEADLINE 任务反转。

2026-07-05 · os

【操作系统百科】实时 OS 巡礼

VxWorks/QNX/Zephyr 与 Linux PREEMPT_RT 的工程取舍——硬实时 vs 软实时、静态调度、ARINC-653 分区、安全认证(DO-178C)、最小内存占用。

2026-06-05 · os

【操作系统百科】线程化中断

把 IRQ handler 线程化——PREEMPT_RT 的核心改造之一。本文讲 request_threaded_irq、handler/thread_fn 分工、IRQF_ONESHOT、全线程化的延迟与吞吐代价、softirq 线程化趋势。

2026-05-31 · os

【操作系统百科】futex

glibc pthread_mutex 背后是 futex——用户态快路径无 syscall,竞争时才进内核。本文讲 FUTEX_WAIT/WAKE、PI futex、robust futex、futex2、requeue、安全补丁与工程陷阱。


By .