当 perf top 显示 [kworker] 或 [ksoftirqd] 占用高 CPU,表明内核线程正高频处理工作队列或软中断,根源多在驱动、中断负载或内核子系统异常;需通过 ps、perf record -g 结合 /proc/interrupts、/proc/softirqs 及 dmesg 定位具体设备与驱动问题,并采取中断绑定、NAPI 调优等措施验证缓解效果。
![perf top 实时显示 [kworker] 或 [ksoftirqd] 热点时的下一步分析](https://img.php.cn/upload/article/001/242/473/176905836930668.jpeg)
当 perf top 实时显示 [kworker] 或 [ksoftirqd] 占用显著 CPU 时,说明内核线程正在高频处理工作队列或软中断任务,这通常指向底层驱动、中断负载或内核子系统异常,而非用户程序问题。下一步分析需聚焦内核行为本身,而非盲目优化应用代码。
确认具体内核线程类型与上下文
先区分是通用工作队列(kworker/u*:*)、绑定 CPU 的工作队列(kworker/0:*),还是软中断线程(ksoftirqd/0):
- 运行
ps -eLf | grep -E "(kworker|ksoftirqd)"查看完整线程名和 CPU 绑定情况 - 配合
perf top -p $(pgrep -f "ksoftirqd/0")单独监控某一个软中断线程的热点函数 - 注意线程名末尾的数字(如
kworker/0:2H中的H表示 high-priority workqueue)
启用调用图并定位触发源头
仅看函数名(如 __do_softirq、process_one_work)不够,必须回溯到谁提交了这些 work 或触发了软中断:
- 用
perf record -g -e irq:softirq_entry -a sleep 5捕获软中断入口,再用perf report --no-children查看调用链 - 对工作队列:运行
perf record -g -e sched:sched_wakeup -C 0 --filter-pid=$(pgrep kworker/0) sleep 5,观察是谁唤醒了该kworker - 若看到大量
nvme_irq、igb_poll、ahci_port_intr等驱动函数,说明对应设备产生高频率中断或 NAPI 轮询压力
关联硬件与驱动状态验证假设
多数 kworker/ksoftirqd 高负载由硬件行为引发,需交叉验证:
- 检查中断分布:
cat /proc/interrupts | head -20,关注某 CPU 上中断计数是否远高于其他 CPU(尤其网卡、NVMe、USB 控制器) - 查看软中断统计:
cat /proc/softirqs,若NET_RX或TIMER列数值每秒增长极快,说明网络收包或定时器调度过载 - 排查驱动问题:例如
dmesg | grep -i "error\|warn\|throttle"是否有网卡丢包重传、NVMe reset、USB reset 等日志
针对性缓解与验证手段
确认根源后,可尝试轻量级干预并快速验证效果:
- 调整网卡 NAPI 权重:
echo 64 > /sys/class/net/eth0/napi_defer_hard_irqs(部分驱动支持) - 绑定中断到特定 CPU:
echo 1 > /proc/irq/XX/smp_affinity_list,避免单核被打满 - 临时关闭非必要服务(如蓝牙、USB gadget、IPv6 router advertisement)观察
kworker是否回落 - 升级固件或内核补丁(如已知某版本
igb驱动在多队列下导致 workqueue 积压)










