麒麟系统排查硬件响应延迟或cpu单核打满问题,必须确认中断是否集中触发、绑定是否失当、单次处理是否超时:先用cat /proc/interrupts看各cpu中断分布,再用lsirq解析设备与irq映射,查smp_affinity_list确认亲和性设置,最后用trace-cmd抓中断处理耗时。

麒麟系统排查硬件响应延迟或CPU单核打满问题,必须确认中断是否集中触发、绑定是否失当、单次处理是否超时,不能只看总量数字。
查/proc/interrupts看各CPU中断分布
执行cat /proc/interrupts,这是内核实时维护的只读文件,反映每个CPU上各类中断(IRQ)自启动以来的触发次数。
重点盯最后一列设备名(如eth0、nvme0n1、i915)和对应CPU列数值——如果某行某列(比如CPU0)每秒涨几百上千,而其他列几乎不动,说明该中断被钉死在单核上“堵车”。
看到IR-PCI-MSI或IR-IO-APIC前缀,是虚拟化环境启用中断重映射的标志,此时IRQ编号已与物理引脚解耦,别按传统编号理解。
数值为0不等于设备没工作——网卡若启用NAPI或轮询模式(ethtool -C eth0 rx off),中断计数归零但流量照常。
用lsirq查设备与IRQ映射关系
先确认工具是否存在:which lsirq。未安装则按系统类型执行:
Ubuntu/Debian系:sudo apt install linux-tools-common
RHEL/CentOS系:sudo yum install kernel-tools
运行sudo lsirq -v,它会把/proc/interrupts原始数据解析成设备名、驱动名、绑定CPU列表、中断类型等可读字段,比手动grep清晰十倍。
快速筛出网卡或NVMe设备:sudo lsirq | grep -i "eth0\|nvme",直接定位关键硬件的IRQ归属。
查中断CPU亲和性设置
第一步:找出目标设备对应的IRQ号。例如查eth0:grep eth0 /proc/interrupts | awk '{print $1}'
第二步:用该IRQ号查其当前绑定的CPU列表:cat /proc/irq/$(grep eth0 /proc/interrupts | awk '{print $1}')/smp_affinity_list
输出是十进制CPU编号(如0,2,3),人眼可读;若显示为空或报错Operation not permitted,说明该IRQ被固件锁定(常见于BMC、老RAID卡),不可修改。
【注意】别直接写smp_affinity(十六进制掩码)——x86和ARM位宽不同,写错会导致中断完全不触发。
第三步:验证是否被irqbalance接管——对比cat /proc/irq/N/effective_affinity和smp_affinity_list,若两者不一致,说明后台服务正在覆盖你的手动设置。
抓单次中断处理耗时
方法一:用trace-cmd抓纳秒级handler生命周期
先确认内核支持:grep CONFIG_IRQSOFF_TRACER /boot/config-$(uname -r),返回y或m才可继续。
执行trace-cmd record -e irq:irq_handler_entry -e irq:irq_handler_exit -T 5,抓5秒内所有中断从入口到出口的完整路径。
分析时重点看delta字段(单位纳秒),超过100μs就值得怀疑驱动在中断上下文里做了太多事(比如memcpy大块数据)。
方法二:用perf采样中断处理函数(仅作辅助)
sudo perf record -e irq:irq_handler_entry -a sleep 10
sudo perf report --sort comm,symbol -g
在报告中查找handle_irq_event_percpu或设备驱动名(如ahci_interrupt)的堆栈项——但注意perf不保证入口/出口配对,无法算真实handler耗时,仅用于识别高频触发点。
区分硬中断与软中断负载
硬中断看cat /proc/interrupts,软中断看cat /proc/softirqs。
运行cat /proc/softirqs | grep -E "^(NET_RX|NET_TX|TIMER|SCHED):",重点关注单核上NET_RX是否线性飙升(比如CPU0从120万→130万→140万)。
若mpstat -P ALL 1显示某核%soft持续>20%,再查对应CPU在/proc/softirqs中哪一列增长最快,就能锁定瓶颈类型。
NET_RX高但NET_TX很低,可能是应用没及时读socket,接收队列堆积;NET_RX和硬件中断数差距极大(比如中断只触发100次,NET_RX却执行了5万次),说明NAPI没生效或驱动在中断上下文里做了太多事。











