1. 中断风暴的真面目:硬中断与软中断的连锁反应
1.1 先搞清楚中断到底在做什么
很多做运维和嵌入式开发的朋友,一听到“中断风暴”这三个字就头皮发麻。我在一线排查过不少服务器假死、网络吞吐暴跌的故障,十次里有三四次都能在日志和性能数据里抓到中断风暴的影子。要理解它,得先把中断机制本身捋清楚。
CPU 在执行指令的时候,随时可能被硬件设备打断,比如网卡收到一个数据包、磁盘完成了读写、定时器到了时间点,这些设备会向 CPU 发送一个电信号,CPU 收到信号后暂停手头的工作,转去执行一段对应的处理程序,处理完再回来继续干活。这个过程就是中断。中断是操作系统的“神经反射”,没有它,CPU 就得轮询所有硬件,效率低得没法看。
Linux 把中断处理拆成了两段。上半部分是硬中断(hardirq),处理器接收到硬件信号后立刻执行,要求速度快、不能阻塞,通常只做最要紧的事,比如把数据从设备复制到内存、标记一个待处理的标志位,然后赶紧返回。下半部分是软中断(softirq),硬中断把重活留给它,比如网络数据包的协议栈处理、块设备的 IO 完成回调,这些工作可以在更合适的时机慢慢做。
这么设计的原因很直白:硬中断执行期间,CPU 在同一个核上不能响应其他中断,如果硬中断处理时间太长,其他设备就会“干等”,甚至丢数据。而软中断可以被调度、可以被抢占,灵活得多。Linux 内核在硬中断处理函数返回前会检查软中断的 pending 位,如果有就顺手处理一批,这样既保证了及时性,又避免中断上下文占用过久。
1.2 中断风暴就是 CPU 被“打断腿”了
中断风暴,简单说就是一段时间内,系统收到中断请求的频率远远超过了它能处理的合理范围,导致 CPU 把大量时间花在处理中断本身上,而不是执行用户进程和业务逻辑。这时候系统负载看着不见得高,但业务就是卡顿、吞吐量上不去,因为 CPU 的时间片全被“偷”走了。
有一个类比特别好理解:你正坐在工位上写代码,旁边有人每隔几秒就拍你肩膀问一句“在吗”。虽然每次问话只有一秒钟,但你的思路完全断了,一上午下来代码没写几行,全在“被打断—恢复—再被打断”的循环里。CPU 遇到中断风暴就是这个状态。
中断风暴有两个层面。一层是硬中断频率本身暴涨,比如网卡在高速收包时每收到一个包就触发一次中断,包量一大,中断频率就跟着飙升。另一层是硬中断频率不高,但每次硬中断触发的软中断处理特别耗时,比如网络数据包处理逻辑重、锁竞争激烈,软中断堆积越来越多,CPU 在 softirq 里消耗的时间占比越来越大。两个层面经常同时出现,搅在一起,排查时容易晕头转向。
判断中断风暴最直接的办法是看系统统计。/proc/interrupts 文件记录了每个 CPU 核上每种中断源触发的次数,两次采样间隔内数值暴涨,说明中断频率异常。另一个是 top 命令里看 CPU 的使用率分布,如果 si(softirq 软中断)长期占据高位,比如超过 30%,那基本可以断定软中断处理成了瓶颈。
注意:si 高不代表一定就是坏事。高吞吐的网络服务器、繁忙的存储节点,软中断占用一部分 CPU 是正常的。真正需要警惕的是 si 数值长期居高不下,同时业务吞吐没有相应增长,或者 CPU 之间负载严重不均衡,某个核的 si 跑到 80% 以上,其他核空闲,这种“一边忙死一边闲死”的状态,十有八九是中断分配出了问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 中断风暴的高发场景:网卡、驱动与硬件异常
2.1 网卡收包中断:最经典的高频中断源
网络设备是中断风暴的头号来源,尤其在高 PPS(每秒数据包数)场景下。以前网卡收包是一个包一个中断,10 兆、100 兆网络时代这没什么问题,但是到了千兆、万兆,小包突发情况下每秒几十万甚至上百万个包,如果每个包都触发一次中断,CPU 就啥也别干了,光响应中断就耗尽算力。
现代网卡普遍支持中断合并(coalescing),驱动可以配置收包后先攒一批再上报中断,或者用定时器周期性检查。中断合并的配置有几个关键参数,比如 rx-usecs 表示收到包后最多延迟多少微秒产生中断,rx-frames 表示攒够多少个帧才产生中断。这两个值调大了,CPU 中断频率降下来了,但延迟会上升;调小了,延迟降低,中断频率上升。实际调优要在延迟和吞吐之间找平衡点。
另一个重要机制是 NAPI。NAPI 是 Linux 网络子系统为了对抗中断风暴设计的经典方案:网卡产生第一个中断后,驱动立刻关掉该队列的中断,然后切换到轮询模式,从环形缓冲区里把数据批量取出来送到协议栈,直到取空了再重新开启中断。这样在高速收包场景下,中断次数和包数不再是一比一的关系,中断数量被压得很低。NAPI 的 weight 参数控制一次轮询最多处理多少个包,默认是 64,处理完如果还有包,就等到下一个软中断周期继续处理。
我在实际排查中见过一个典型的反面案例。有台服务器做流量转发,万兆网卡,业务方反馈转发性能只有预期的一半。抓数据发现每个 CPU 核的硬中断次数并不高,但是某个核的 si 占用到了 90% 以上,其他六个核几乎空闲。原因是网卡只有一个队列,所有收包中断都路由到了 CPU0,CPU0 在软中断里处理大量的包,其他核帮不上忙。后来把网卡多队列打开,配置了 Receive Side Scaling(RSS),让不同队列的中断分散到不同 CPU 核,再配合 RPS(Receive Packet Steering)做软件层面的负载均衡,吞吐直接翻倍。这类问题本质上不是中断频率失控,而是中断负载分布不均导致的局部“风暴”。
2.2 驱动缺陷:中断请求却无事可做
驱动代码写得不讲究,也会人为制造中断风暴。有一种常见的情形是设备中断状态没有及时清除。中断处理程序跑完忘记写清除寄存器,或者清状态的时序不对,设备认为 CPU 还没处理完,立刻又发一个中断,CPU 再进中断处理程序,
