直接看 /proc/interrupts 就够了,但需理解其结构:第一列为 irq 编号,后续各列为对应 cpu 的触发次数,最后一列为中断类型及设备名;数值突增而无对应进程运行,多因硬件抖动或驱动异常。

直接看 /proc/interrupts 就够了,但得会读——它不报错、不预警,只默默记录每个 CPU 上每个 IRQ 被触发了多少次;数值突增却没对应进程在跑,八成是硬件抖动或驱动异常。
怎么看懂 /proc/interrupts 的列和行
执行 cat /proc/interrupts 后,第一列是 IRQ 编号(比如 25 可能是 NVMe,1 是键盘),后面每列代表一个 CPU(CPU0、CPU1…),最后一列是中断源描述,常见形式有:
-
IO-APIC 16:传统 IO-APIC 中断,编号绑定物理引脚 -
PCI-MSI 0000:01:00.0:PCIe 设备用 MSI 方式申请的中断,编号与设备地址强关联 -
IR-PCI-MSI 32768:启用了中断重映射(IRQ remapping)的虚拟化环境,此时 IRQ 编号已和物理引脚解耦 -
nvme0n1或eth0:内核驱动注册时填的设备名,最直观的归属线索
注意:0 不等于“没工作”——像网卡启用 NAPI 或轮询模式(ethtool -C eth0 rx off)后,中断计数会归零,但设备仍在高效收包。
怎么快速定位异常中断源
单纯扫屏容易漏掉慢速爬升或周期性尖峰,建议组合命令抓特征:
- 监控前 20 行每秒变化:
watch -n 1 'cat /proc/interrupts | head -20',重点盯某列是否非线性跳变(如CPU0列从 12000 → 15000 → 19000,而其他列几乎不动) - 筛出 PCI/MSI 类中断(通常是性能关键设备):
grep -E 'PCI|MSI' /proc/interrupts - 按设备名统计触发频次:
awk '{print $(NF)}' /proc/interrupts | sort | uniq -c | sort -nr | head -10 - 查某设备绑在哪个 IRQ:
grep eth0 /proc/interrupts | awk '{print $1}',再拿这个数字去查亲和性
常见陷阱:看到 i915(Intel 核显)中断暴涨,别急着怀疑显卡——可能是 DRM 驱动在做页面翻转或电源状态切换,需结合 trace-cmd 看 handler 耗时才能确认是否真卡顿。
为什么不能只信 /proc/interrupts 的总数
它只告诉你“触发了多少次”,不告诉你“每次花了多久”“有没有延迟堆积”“是不是被屏蔽了”。典型问题场景:
- 数值平稳但系统偶发卡顿?→ 用
trace-cmd record -e irq:irq_handler_entry -e irq:irq_handler_exit -T 5抓单次中断生命周期,看delta字段是否持续 >100μs - 某 IRQ 计数为 0,但设备明明在工作?→ 检查是否启用了轮询(
ethtool -c)、NAPI 或 polling mode,这些绕过传统中断路径 - 虚拟机里看到大量
IR-IO-APIC?→ 这是 KVM 做中断注入的痕迹,真实物理中断可能被合批或延迟,/proc/interrupts在 guest 里反映的是虚拟中断流
真正要定位抖动或延迟敏感问题,/proc/interrupts 只是起点——它像心电图的基线,能看出节律是否整齐,但看不出某次心跳有没有缺血。
查中断绑核用 smp_affinity_list,别碰 smp_affinity
想确认某个 IRQ(比如 42)绑在哪些 CPU 上,直接读:cat /proc/irq/42/smp_affinity_list。输出是易读的十进制编号,例如 0,2,4 表示只分发到 CPU 0/2/4。
千万别手写十六进制掩码到 smp_affinity,因为:
- x86_64 默认 64 位掩码,ARM64 可能更宽,写错一位就全失效
- 内核可能开启 IRQ 自动负载均衡(
irqbalance服务),你刚写完就被覆盖 - 先看
/proc/irq/42/effective_affinity,如果它和smp_affinity_list不一致,说明有更高优先级策略在干预
需要固定绑核时(如低延迟交易、DPDK),优先停掉 irqbalance,再用 echo "0,1" | sudo tee /proc/irq/42/smp_affinity_list,比硬写十六进制安全得多。











