hardirq 时间越短越好——但有些设备需要在中断上下文做 I2C 通信、DMA 等待。线程化中断把这些工作搬到内核线程。
一、先看图
flowchart LR
IRQ[硬件中断] --> HANDLER[hardirq handler<br/>快速确认]
HANDLER -->|IRQ_WAKE_THREAD| THREAD[irq thread<br/>内核线程]
THREAD --> WORK[完整处理<br/>可睡眠]
classDef hard fill:#f85149,stroke:#f85149,color:#adbac7;
classDef thread fill:#3fb95022,stroke:#3fb950,color:#adbac7;
class IRQ,HANDLER hard
class THREAD,WORK thread
二、API
request_threaded_irq(irq, handler, thread_fn, flags, name, dev_id);- handler:hardirq
上下文,做最小工作(ACK 硬件)→ 返回
IRQ_WAKE_THREAD - thread_fn:内核线程上下文,完成实际处理 → 可睡眠
2.1 IRQF_ONESHOT
request_threaded_irq(irq, NULL, thread_fn, IRQF_ONESHOT, ...);handler 为 NULL → 内核用默认 handler(只 mask 中断)。
IRQF_ONESHOT:中断在 thread_fn 完成前保持 masked → 防止中断风暴。
I2C/SPI 传感器驱动常用这个模式。
三、PREEMPT_RT 全线程化
PREEMPT_RT 强制所有中断线程化(除
IRQF_NO_THREAD):
// 普通内核
spin_lock_irqsave → 关中断
// PREEMPT_RT
spin_lock → rt_mutex → 可被更高优先级线程抢占
// 中断 handler 在线程中运行 → 也可被抢占效果:所有代码路径可抢占 → 确定性延迟。
四、延迟 vs 吞吐
| 模式 | 中断延迟 | 吞吐量 |
|---|---|---|
| hardirq | 最低 | 最高 |
| threaded IRQ | 略高(调度开销) | 略低 |
| PREEMPT_RT 全线程 | 确定性(< 50μs) | 降低 5-15% |
4.1 实时延迟
cyclictest 测量:
cyclictest -m -Sp99 -i200 -h400 -q -l 100000- 普通内核:p99 ~50-200μs(偶尔 ms 级尖刺)
- PREEMPT_RT:p99 < 50μs
五、softirq 线程化
PREEMPT_RT 也把 softirq 线程化 → ksoftirqd 成为可调度线程 → 不再抢占用户态。
主线内核 6.x 开始逐步合入 softirq 线程化改造。
六、中断风暴的变形
线程化中断可能引入新问题:
- thread_fn 执行慢 → 中断队列堆积
- ONESHOT mask 时间过长 → 设备响应延迟
需要监控 IRQ 线程的调度延迟。
七、何时用线程化中断
| 场景 | 建议 |
|---|---|
| I2C/SPI 设备 | 线程化(需要总线通信) |
| 高速网络/NVMe | 保持 hardirq(性能) |
| 通用设备驱动 | 线程化 + ONESHOT |
| 实时系统 | PREEMPT_RT 全线程化 |
八、irq thread 优先级
ps -eo pid,cls,rtprio,comm | grep irq/
# irq/42-nvme0q1 FF 50IRQ 线程默认 SCHED_FIFO 50。可以用 chrt
调整。
实时系统需要仔细规划 IRQ 线程优先级 → 避免优先级反转。
九、观察
cat /proc/interrupts # 中断计数
ps -eo pid,cls,rtprio,comm | grep irq/ # IRQ 线程
cat /proc/irq/<n>/spurious # 虚假中断
# 线程化中断延迟
bpftrace -e 'kprobe:irq_thread_fn { @lat = hist(nsecs - @start[tid]); }'十、小结
- 线程化中断把 handler 搬到内核线程 → 可睡眠、可抢占
- IRQF_ONESHOT 防止中断风暴
- PREEMPT_RT 全线程化 → 确定性延迟 < 50μs
- 代价是吞吐量降低 5-15%
- 高速设备保持 hardirq,慢速设备用线程化
参考文献
kernel/irq/manage.c- Thomas Gleixner, “RT PREEMPT HOWTO.”
Documentation/kernel-hacking/locking.rst- Steven Rostedt, “Threaded interrupts and preemptible-RCU.” 2009
工具
- cyclictest
chrt/proc/irq/<n>/- bpftrace
上一篇:softirq/tasklet/workqueue 下一篇:定时器
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【操作系统百科】实时 OS 巡礼
VxWorks/QNX/Zephyr 与 Linux PREEMPT_RT 的工程取舍——硬实时 vs 软实时、静态调度、ARINC-653 分区、安全认证(DO-178C)、最小内存占用。
【操作系统百科】优先级反转与继承
火星探路者号因优先级反转重启——这是实时系统最经典的故事。本文讲优先级反转现象、PIP 优先级继承协议、PCP 优先级天花板、rt_mutex、PREEMPT_RT 的 spinlock 转换、DEADLINE 任务反转。
【操作系统百科】SCHED_FIFO/RR 与 PREEMPT_RT
Linux 里的实时:SCHED_FIFO/RR 提供优先级调度,但原版内核仍有不可抢占点。PREEMPT_RT 补丁集 20 年后(6.12)合入主线,把几乎所有 spinlock 变 rt_mutex、IRQ 变线程。本文讲 RT 调度语义、RT-throttling、cyclictest 基线、优先级继承、以及 RT 部署的陷阱。
【操作系统百科】内存回收
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。