ksoftirqd高CPU占用本质是网卡收包速率超协议栈处理能力,需通过多队列、中断亲和、调优netdev_budget等降低softnet backlog。

ksoftirqd 占用高 CPU(20~40%)且伴随 sof.net backlog 持续堆积,本质是内核软中断处理网络收包不及时,不是 ksoftirqd 本身有问题,而是它在“拼命干活”——说明网卡收包速率超过了协议栈处理能力。调优核心是:**让硬件收得更稳、内核处理得更快、队列堆积得更少**。
检查并确认瓶颈来源
先排除误判:
- 运行 cat /proc/net/softnet_stat,逐列看每 CPU 的第 1 列(processed)、第 2 列(dropped)、第 3 列(time_squeeze)。若某 CPU 的 time_squeeze 长期增长快,说明该 CPU 软中断处理不过来;dropped 非零则已丢包。
- 用 perf top -g -p $(pgrep ksoftirqd) 看热点函数,常见如 napi_poll、__netif_receive_skb_core、ip_rcv,确认是否卡在协议栈上层(如 iptables、conntrack)或底层驱动。
- 检查是否单队列网卡绑定到单个 CPU,导致负载不均。执行 ethtool -l ethX 查看当前通道数,cat /proc/interrupts | grep ethX 看中断分布是否集中。
网卡多队列与中断亲和性调优
让多个 CPU 分担收包压力,避免单核瓶颈:
- 启用多队列:ethtool -L ethX combined N(N 通常设为 CPU 核心数或略少),再确认 ethtool -l ethX 显示 rx/tx 队列已生效。
- 绑定每个 RX 队列中断到不同 CPU:echo "CPU_MASK" > /proc/irq/IRQ_NUM/smp_affinity_list,建议按 NUMA 节点分组,例如 CPU 0-3 绑定队列 0-3,CPU 4-7 绑定队列 4-7。
- 开启 RPS(软件层面补充负载均衡):对非多队列网卡或需要跨 CPU 分流时有效。echo "FF" > /sys/class/net/ethX/queues/rx-0/rps_cpus(十六进制掩码表示 CPU 位图)。
调整内核网络参数降低 backlog 压力
控制入队节奏与处理深度,防止 softnet backlog 溢出:
- 增大 per-CPU softnet backlog 队列长度(默认 1000):sysctl -w net.core.netdev_max_backlog=5000。注意过高会增加延迟,5000~10000 是较安全起点。
- 限制单次软中断处理的包数,避免长时间占用 CPU:sysctl -w net.core.netdev_budget=300(默认 300,可尝试 150~600 区间,需实测平衡吞吐与 latency)。
- 关闭可能拖慢收包路径的功能:如非必要,禁用 net.bridge.bridge-nf-call-iptables=0、net.ipv4.conf.all.rp_filter=0(仅限可信内网)。
驱动与固件层面优化
很多问题根源在驱动或硬件配置:
- 升级网卡驱动和固件(尤其是 Intel ixgbe、i40e、mlx5 等),旧版本存在 NAPI 调度缺陷或队列唤醒延迟。
- 关闭 LRO/GRO(巨型帧重组):ethtool -K ethX lro off gro off。GRO 在高并发小包场景下反而加剧 softirq 压力,建议只开 GSO(发送端)。
- 调整 Ring Buffer 大小:ethtool -G ethX rx 4096 tx 4096(根据内存和流量特征调,避免过小溢出、过大增缓存压力)。
调优后持续观察 /proc/net/softnet_stat 和 top 中 ksoftirqd 的 CPU 使用率变化,重点看 time_squeeze 是否收敛、dropped 是否归零。多数情况下,合理设置多队列 + 中断亲和 + netdev_budget 控制,即可将 ksoftirqd 占用压至 5% 以下。








