第94期 | 多核时代,谁来听门铃
一、中断也有门牌号
SMP 机器普及之后,中断落下个默认的坏习惯——全挤在 CPU0 身上。2014 年还有人专门写教程提醒:中断通常只由第一个核处理¹。门铃只在一个房间响,别的房间再空,也帮不上忙。
PCI 3.0 规范带来 MSI-X²:设备不再拉一根电平线喊话,而是往特定内存地址写一个数——中断变成了一次内存写。一个设备最多可以有 2048 个向量³,每个向量有自己独立的地址、数据和屏蔽位。网卡终于能"一队一中断号":收包队列 0 的中断走向量 0,队列 1 走向量 1。门铃从此有了门牌号。
2006 年,irqbalance 守护进程出现⁴:用户态的一个小管家,定期看每块设备的中断量,把 IRQ 逐个分给各核,顺手照顾 NUMA 和缓存亲缘性。它的手只有两只:--oneshot,跑一次就走;--banirq,把某些中断排除在外,留给人手动绑。
2010 年,Google 的 Tom Herbert 把 RPS/RFS 送进 2.6.35⁵:网卡中断落在核 A,收包的应用却跑在核 B——包在 A 的缓存里热着,应用在 B 等着,两边都别扭。RPS 在软件里给包算个哈希,按哈希把包塞进目标核的待办队列;RFS 再进一步,直接把同一条流送到应用所在的核——把话递到对的人手里。当年 LWN 上的测试数据很实在:8 核服务器,tg3 网卡从每秒 9 万次事务涨到 28.5 万次⁶。
但亲和性是软约束。内核文档里写得明白:有些机器上跑着 irqbalance,它会动态优化 IRQ 分配,"可能覆盖掉你手动的设置"⁵。想自己说了算,得先跟管家打好招呼——要么 --banirq,要么停掉它。
照见一层:单核变多核,不是"一个 CPU 乘以 N"。Anderson 早在 1972 年就写过"多即不同"⁷:每一层级都需要新概念。单核时代不存在"门铃挂哪"的问题——中断亲和性,是多核这一层长出来的新概念。发展性研究之眼补一句:MSI-X、irqbalance、RPS/RFS,没有一个发明新原理,全是把已有的能力接好、把"门铃挂哪"这件事做扎实。先实际,后原理——Linux 赢的从来是这一套。
二、门铃拧在干活的人门口
如果 AI 先做 OS,它不会把亲和性当事后补丁。门铃在设备枚举时就一次排好:网卡队列的内存、收包的核、跑推理的算力片,三者在同一个 NUMA 节点、同一片缓存域里相遇。MSI-X 表不再由驱动随便填,而由 OS 的排布引擎统一写——中断投递从"先乱发、再收拾"变成"一次排好"。
有个印证,就在上周。2026 年 10 月 21 日,一篇 Linux 内核网络子系统的长文⁸,FAQ 第一问还是这个:top 里看到某个核的 %si 跑满 100%,别的核闲着——病因:中断亲和性没调好,或者网卡单队列。药方:开多队列 RSS、跑 irqbalance 或手写 smp_affinity、再配 RPS/RFS。二十年过去,生产环境的第一问还是同一道。这说明亲和性不是调优技巧,是结构。
另一头,"打断"这件事本身正在被改写。2024 年 9 月 20 日,Thomas Gleixner 的 pull request 被 Linus 合入主线——PREEMPT_RT 二十年长征到站⁹。内核官方文档把它的硬功夫写得很直白:强制线程化中断¹⁰——中断处理函数跑在进程上下文里,由调度器调度,默认 SCHED_FIFO 优先级 50。门铃响了,不再是"停下手里的活去开门",而是"有个线程在排队等开门"。实时不是更快,是最坏情况也可预期。
范式之眼:线性时代,中断亲和性按 CPU 时间片排;向量阵列时代,该按算力阵列的占用排——正在跑推理的核,网卡中断别去凑热闹。亲和性这套机制,是旧抽象(中断=停下 CPU)在新硬件(多核、NUMA、加速器)上的补丁史。AI-native OS 该原生地想:事件发生的那一刻,数据、算力、通知三者在物理上就该是邻居。
三、亲手给中断换个房间
手边任何一台 Linux 机器,今晚就能动手。
- 看总账:cat /proc/interrupts——哪一列数字在涨,门铃就响在哪个房间。
- 看门牌:cat /proc/irq/<中断号>/smp_affinity_list,再看 effective_affinity_list——前者是你写的愿望,后者是硬件认的现实。
- 看管家:systemctl status irqbalance;想看它怎么做决策,前台跑一次:irqbalance --oneshot --debug,跑完就退出,不留守护进程。
- 手动搬:先跟管家打招呼(irqbalance --banirq=<中断号>,或停掉服务),再写:echo 2 > /proc/irq/<中断号>/smp_affinity,把它绑到 CPU1。搬完回头看 /proc/interrupts,涨的列跟着走了。
- 网卡有几副门牌:ls /sys/class/net/<网卡名>/queues/——有几个 rx-N,就有几个向量可挂;单队列的老网卡,用 RPS 补:echo f > /sys/class/net/<网卡名>/queues/rx-0/rps_cpus,把收包处理散给 CPU0~3。
- 看线程化的中断:ps -e | grep 'irq/'——PREEMPT_RT 内核上,中断处理是看得见的线程,有名字、有优先级,能被调度器排队。
可观察的现象:找台有流量的机器(或自己打 iperf3),盯着 /proc/interrupts 里网卡那一行,看某一列往上窜;手动换绑后,窜的列跟着走。亲手拨一次,比看十遍文档记得牢。
同一张表有四种读法:一台跑本地模型的机器上,推理服务收请求走网卡中断,把网卡队列绑到推理线程之外的核——上一期那个单核上 BPF 循环和 softirq 抢 CPU、P99 差 2.6 倍的实测,就是门铃挂错房间的代价;边缘小盒子上,视频流进、推理出,两路中断别挤在同一个小核上,大小核之间更要讲究亲缘性;视频 AI 平台里,摄像头事件"有事才唤醒",唤醒后最好落在处理那路流的核上,少一次跨核搬运;企业私有智能中心里,告警与工单也该像中断一样带优先级进队,而不是让人在库里一遍遍轮询刷。
门铃的门牌号:网卡多队列经 MSI-X 各挂一个向量,irqbalance 与手写亲和性决定每个向量响在哪个核,RPS/RFS 再把包递到应用所在的核。程序绘制概念示意图。
觉 然 小 注
门铃响在谁的门口,决定了谁被打扰、谁得清静。凡发生必有利于我——每一次中断都是世界在递话;把话递到对的人手里,少一次跨核搬运,就多一分算力留给真正要想的事。不慌,不堵,各安其位——谢赫说的"经营位置"¹¹,大抵就是这个意思。
引 用 与 出 处
- [1] thegeekstuff. Introduction to Linux Interrupts and CPU SMP Affinity. 2014. https://www.thegeekstuff.com/2014/01/linux-interrupts/
- [2] Microsoft Learn. Introduction to Message-Signaled Interrupts. (PCI 2.2 的 MSI 与 PCI 3.0 的 MSI-X:设备以内存写代替电平线触发中断;MSI-X 每设备最多 2048 个消息). https://learn.microsoft.com/vi-vn/windows-hardware/drivers/kernel/introduction-to-message-signaled-interrupts
- [3] Linux 内核文档. MSI-HOWTO.txt(MSI-X 表项上限 2048;按向量屏蔽是 MSI-X 必备特性). https://mjmwired.net/kernel/Documentation/MSI-HOWTO.txt
- [4] irqbalance(1) man page.(守护进程:将硬件中断分发到多处理器各核;--oneshot/--banirq;man 页落款 2006 年 12 月). https://www.unix.com/man-page/linux/1/irqbalance
- [5] Linux 内核文档. Documentation/networking/scaling.rst(RPS/RFS 进 2.6.35,补丁原作者 Tom Herbert;irqbalance 会覆盖手动设置). https://mjmwired.net/kernel/Documentation/networking/scaling.rst
- [6] LWN.net. Receive packet steering. 2010. https://lwn.net/Articles/362339/
- [7] P. W. Anderson. More is Different: Broken Symmetry and the Nature of the Hierarchical Structure of Science. Science 177(4047), 1972.(思想化用) https://www.ifsc.usp.br/~hoyos/courses/2018/SFI5734/Science-Anderson.pdf
- [8] dev.to. Linux Kernel Networking Subsystem in Depth: From NIC Drivers, NAPI, and Ring Buffers to eBPF XDP Wire-Speed Forwarding. 2026-10-21. https://dev.to/ifnodoraemon/linux-kernel-networking-subsystem-in-depth-from-nic-drivers-napi-and-ring-buffers-to-ebpf-xdp-2hon
- [9] hackster.io. Linux Can Now Power Real-Time Operating Systems, as the PREEMPT_RT Patch Set Is Merged Into Mainline. 2024. https://www.hackster.io/news/linux-can-now-power-real-time-operating-systems-as-the-preempt-rt-patch-set-is-merged-into-mainline-dde8fe8c7308.amp
- [10] Linux 内核文档. The Linux Kernel: Real-time theory.(PREEMPT_RT 强制线程化中断:处理函数跑在进程上下文、由调度器调度,默认 SCHED_FIFO 优先级 50). https://www.kernel.org/doc/html/latest/core-api/real-time/theory.html
- [11] 谢赫. 《古画品录》序(六法其五"经营位置"). (思想化用)
· · ·