写入 smp_affinity 未生效主因是 irqbalance 运行、驱动自管理或内核禁用干预;应停用 irqbalance、优先用 smp_affinity_list、验证 /proc/interrupts 实时计数及 perf 抓取中断实际 cpu。

为什么写入 smp_affinity 没生效?
写入后 cat /sys/kernel/debug/x86/smp_affinity 看值变了,但中断没真跑到指定 CPU 上——大概率是内核禁用了手动设置,或者设备驱动绕过了它。
- 检查是否启用了中断亲和性控制:
cat /proc/sys/kernel/irq_affinity,输出为1才允许用户态干预 - 某些驱动(如
igb、ixgbe)默认启用irqbalance或自管理 IRQ 分发,会覆盖你写的值 -
smp_affinity是十六进制位掩码,但部分老内核(如 3.10)只接受 32 位宽格式;若 CPU 数 > 32,得用smp_affinity_list - 写入前确认 IRQ 号对应设备正在运行:
grep -r "eth0" /sys/class/net/*/device/msi_irqs/或查/proc/interrupts
smp_affinity 和 smp_affinity_list 怎么选?
二者功能一样,但接口形态不同:前者是传统 hex 位图,后者是更直观的 CPU ID 列表(如 0,2-4),从 Linux 4.7+ 开始推荐用后者。
-
smp_affinity必须用小写十六进制,高位在左,例如 4 核机器上绑 CPU 1 和 3 →0xa(二进制1010) -
smp_affinity_list支持范围写法,可读性强,且自动处理 >32 CPU 的情况;但部分旧驱动未实现该接口,写入会报Invalid argument - 优先尝试
smp_affinity_list;失败再回落到smp_affinity,并用printf "%x\n" $((2**0 + 2**2))算位掩码
绑定后性能反而下降?常见干扰点
中断亲和性不是“绑得越死越好”,尤其在 NUMA 架构或高吞吐网卡场景下,容易触发缓存颠簸或内存带宽争抢。
- CPU 和网卡不在同一 NUMA 节点时,强制绑本地 CPU 可能导致远程内存访问延迟飙升
- 多个中断绑到同一个 CPU,可能造成该核软中断处理堆积,
top -p $(pgrep ksoftirqd)可观察 -
irqbalance服务如果开着,会定时重置亲和性;停掉它:systemctl stop irqbalance,并mask防止开机启动 - 某些网卡支持 RSS(Receive Side Scaling),应优先配 RSS key + indirection table,而非硬绑单个 IRQ
如何验证中断真跑在目标 CPU 上?
别只信 smp_affinity 文件内容,要看实时流向。
- 持续监控:
watch -n1 'grep "eth0" /proc/interrupts',观察各 CPU 列数字是否增长(注意列序对应/proc/cpuinfo中的processorID) - 确认当前 IRQ 绑定状态:
cat /proc/irq/$(grep eth0 /proc/interrupts | awk '{print $1}' | sed 's/:$//')/smp_affinity_list - 用
perf record -e irq:irq_handler_entry -- sleep 5抓取中断事件,再perf script | grep -E "(eth|enp)"看 handler 运行在哪颗 CPU 上
真正难的是动态负载下保持亲和稳定——比如容器热迁移、CPU hotplug、驱动 reload 都可能清空设置。这类场景建议把绑定逻辑写进 udev rule 或 systemd service,而不是只做一次手工写入。










