Linux irqbalance 的 –oneshot 模式与中断亲和性手动调整对比

1次阅读

irqbalance –oneshot 不持久生效,因其仅单次计算后退出,不驻留也不监听变化,与后台 irqbalance 服务互不干扰,常被误判为生效实为巧合;持久绑定须停服务后手动写 /proc/irq/n/smp_affinity_list。

Linux irqbalance 的 –oneshot 模式与中断亲和性手动调整对比

irqbalance –oneshot 为什么不会持久生效

irqbalance --oneshot 只是触发一次当前中断分布重计算,然后退出进程,不驻留、不监听后续设备热插拔或中断负载变化。它和 systemd 服务里的 irqbalance 守护进程互不干扰——哪怕你刚跑完 --oneshot,后台的 irqbalance 服务过几秒就可能把亲和性又改回去。

常见错误现象:taskset -c 0-3 cat /proc/interrupts 看到某 IRQ 的 smp_affinity_list 被设成了 0-3,但 10 秒后变回 0,1,2,3 或自动跳到其他 CPU;或者 systemctl restart irqbalance 后配置全丢。

  • 它适合临时诊断:比如刚插上 NVMe 卡,想立刻看 irqbalance 当前“认为”最优怎么分,而不是真要锁死
  • 它不写任何配置文件,也不修改 /proc/irq/*/smp_affinity_list 的值(那是内核接口,irqbalance 自己只读不写)
  • 如果你看到它“生效了”,大概率是巧合——刚好 irqbalance 守护进程还没来得及刷新,或者你误把 --debug 输出当成了实际设置

手动写 smp_affinity_list 的正确姿势

真正能锁定中断亲和性的,只有直接往 /proc/irq/<em>N</em>/smp_affinity_list 写入 CPU 列表。但这个操作有硬性前提:对应 IRQ 必须没被 irqbalance 管理,否则会被覆盖。

使用场景:网卡 RX 队列绑定固定 CPU 做零拷贝收包、DPDK 应用独占中断、避免跨 NUMA 访问延迟。

  • 先停掉 irqbalance:systemctl stop irqbalance,否则它每 10 秒左右会扫描并重写所有 smp_affinity_list
  • 确认 IRQ 号:从 /proc/interrupts 找对应设备行,比如 45: 123456 0 0 0 PCI-MSI 123456 edge eth0-TxRx-0,IRQ 是 45
  • 写入 CPU 列表:echo 0-3 | sudo tee /proc/irq/45/smp_affinity_list(注意必须用 tee,重定向 > 会被权限拒绝)
  • 验证是否生效:cat /proc/irq/45/smp_affinity_list,输出应为 0-3;再看 /proc/interrupts 对应列的计数是否只在 CPU0~3 上增长

irqbalance 关闭 vs 手动绑定的性能差异在哪

irqbalance 动态调优的代价是中断迁移开销 + 统计延迟;手动绑定省掉这些,但失去自适应能力。差别不是“快多少”,而是“稳不稳定”。

参数差异:irqbalance --banirq=45 可以让 irqbalance 忽略某 IRQ,但它仍会管理其他中断,且 --banirq 不持久(重启 irqbalance 服务即失效);而停掉服务 + 手动写 smp_affinity_list 是彻底交出控制权。

  • 高吞吐低延迟场景(如 25G 网卡满速收包):手动绑定通常更稳,避免 irqbalance 在 CPU 负载突增时把中断迁到忙 CPU 上导致丢包
  • 多设备混合负载(USB、SATA、GPU、网卡共存):irqbalance 往往比人脑预设更均衡,尤其在负载波动频繁时
  • 兼容性影响:某些老内核(smp_affinity_list 写入支持不全,写入后 cat 显示正常但中断仍在所有 CPU 上触发,需查 dmesg | grep -i irq 看警告

容易被忽略的 NUMA 和中断亲和性陷阱

单纯按 CPU 编号绑亲和性,可能跨 NUMA node,导致内存访问延迟翻倍。比如 CPU0~3 属于 Node0,CPU4~7 属于 Node1,但你把网卡 IRQ 绑到 CPU0 和 CPU6,就会有一半中断处理在远端内存上跑。

验证方式:lscpu | grep -E "(NUMA|CPU(s))" 看 topology,再结合 cat /sys/devices/system/node/node*/cpulist 确认每个 node 的 CPU 范围。

  • 最佳实践:优先把设备 IRQ 和它 DMA 内存所在的 NUMA node 对齐,例如网卡物理插在 PCIe Slot 连接 Node0,则只绑 CPU0~3
  • PCIe 设备的 NUMA node 查法:lspci -vv -s $(ethtool -i eth0 | awk '/bus-info/ {print $NF}') | grep NUMA
  • 如果 /proc/irq/<em>N</em>/smp_affinity_list 写入后中断计数没变化,先检查该 IRQ 是否被标记为 PER_CPU(如 IPI、timer),这类中断不能手动绑定

最麻烦的不是不会设,而是设完忘了关 irqbalance,或者绑了 CPU 却没同步调优应用线程亲和性——中断来了,处理它的线程却被调度到别的 CPU 上,缓存全丢。

text=ZqhQzanResources