/proc/interrupts 仅统计中断触发次数,无法反映延迟;真实延迟需用 cyclictest 测量中断对实时线程的影响,trace-cmd 定位高耗时中断,irqsoff tracer 排查内核关中断问题。

/proc/interrupts不能查看中断响应延迟——它只记录触发次数,不包含任何时间信息。真实延迟必须用实时性观测工具,在启用 RT 补丁或低延迟内核的前提下测量。
为什么 /proc/interrupts 看不出延迟
执行 cat /proc/interrupts 后看到的数字(比如 45: 1234567 0 0 0 PCI-MSI-edge eth0-rx-0)只是自启动以来该中断在各 CPU 上被触发的累计次数。哪怕某次中断处理花了 200μs,这个文件里也完全体现不出来。
- 数值突增但无对应流量?大概率是硬件误报或驱动 bug,不是“忙”,而是“错”
- 数值为 0?不代表设备没工作——网卡启用 NAPI 或轮询模式(
ethtool -C eth0 rx off)后中断计数归零,但收包照常 - 虚拟化环境里出现
IR-PCI-MSI前缀,说明 IRQ 编号已与物理引脚解耦,不能按传统编号理解
用 cyclictest 暴露中断对调度的干扰
cyclictest 不测纯硬件中断响应,但它能反映中断实际影响——即高优先级实时线程被中断抢占后恢复执行的延迟,这才是业务感知到的“卡顿”根源。
- 安装:
sudo apt install rt-tests(Debian/Ubuntu)或sudo yum install rt-tests(RHEL/CentOS) - 基础命令:
cyclictest -t1 -p99 -i1000 -l10000(单线程、SCHED_FIFO 99、每 1000μs 触发一次、跑 10000 次) - 加压测试:
taskset -c 0 cyclictest -t1 -p99 -i1000 -l10000 & stress --vm 1 --vm-bytes 1G & ping -f 192.168.1.1,观察Max Latency是否突增 - 注意:
cyclictest的延迟值受中断 handler 耗时、锁竞争、内存带宽等共同影响,它不区分原因,只告诉你“这里出问题了”
用 trace-cmd 定位具体中断耗时
当 cyclictest 显示异常延迟,下一步必须确认是哪个中断在拖慢系统。关键看 irq_handler_entry 到 irq_handler_exit 的 delta 时间(单位纳秒)。
- 抓 5 秒数据:
sudo trace-cmd record -e irq:irq_handler_entry -e irq:irq_handler_exit -T 5 - 分析结果:
sudo trace-cmd report | grep -A5 -B5 "eth0\|nvme",快速筛选目标设备相关行 - 重点关注 delta 字段:超过 100μs 就值得怀疑——常见原因是驱动在中断上下文中做
memcpy、调用可能阻塞的函数、或持有自旋锁太久 - 别用
perf record -e irq:*:它不保证入口/出口配对,采样精度也不够算真实 handler 耗时
用 irqsoff tracer 测中断关闭时间
某些场景下,系统卡顿并非来自外部中断,而是内核自身长时间关中断(比如在 spinlock 区域或 critical section 中)。这时 irqsoff tracer 才是直接证据。
- 确认内核支持:
grep CONFIG_IRQSOFF_TRACER /boot/config-$(uname -r)输出应为y或m - 启用追踪:
echo irqsoff > current_tracer && echo 1 > tracing_on,然后复现问题,再echo 0 > tracing_on - 查看结果:
cat trace,关注最大中断关闭时间(max latency)和对应调用栈 - 常见诱因:驱动中不当使用自旋锁、DMA 映射未预分配、或内核模块在 atomic 上下文调用
kmalloc(GFP_KERNEL)
真正影响实时任务的,从来不是“中断有没有来”,而是“来了之后多久才开始处理”以及“处理花了多久”。这三个工具要配合着用:cyclictest 发现抖动、trace-cmd 锁定肇事中断、irqsoff 排查内核自身关中断行为——漏掉任意一环,都可能把硬件问题误判成配置问题,或者把驱动 bug 当作负载过高。











