确认系统是否存在活跃workqueue的最快速方式是执行ps -ef | grep '[kworker]',若有输出说明内核已加载workqueue子系统;kworker进程由kthreadd(pid=2)派生,名称如kworker/0:1h中0表示cpu编号、1为worker id、h代表高优先级队列。

怎么确认系统里有没有活跃的 workqueue?
直接看 kworker 进程是否存在,是最快速的判断方式。工作队列靠内核线程驱动,这些线程统一叫 kworker,名字带斜杠和编号(如 kworker/0:1H),不是随便起的。
执行:ps -ef | grep '\[kworker\]'
如果输出里有若干行以方括号包裹的 kworker,说明工作队列机制正在运行。没输出 ≠ 没启用,只是当前没任务排队;但有输出,就证明内核已加载并维护着 workqueue 子系统。
-
kworker/0:1H中的0表示 CPU 0,1是该 CPU 上第 1 个 worker ID,H表示 high-priority(高优先级队列) - 普通非 H 后缀(如
kworker/1:2)对应的是默认优先级 workqueue - 所有
kworker都由内核的kthreadd(PID=2)派生,不是用户态进程
怎么查某个 workqueue 的当前积压任务数?
Linux 内核不提供通用接口直接读取任意 workqueue 的 pending 工作项数量——它没有暴露成 /proc 或 /sys 下的可读文件。但你可以间接观察:
- 用
cat /proc/sys/kernel/workqueue/active(如果存在)——注意:该路径在多数发行版内核中**不存在**,仅部分定制或新版内核(≥5.10)可能支持,别硬试 - 更可靠的做法是结合
/proc/interrupts和workqueue相关 tracepoint:启用trace-cmd record -e workqueue:* -e irq:* -e sched:sched_wakeup,再分析 trace,但这是调试级操作,不适合日常监控 - 实际工程中,如果你自己定义了
struct work_struct并调用queue_work(),应在驱动或模块里加计数器变量(比如 atomic_t pending_cnt),通过 debugfs 导出——这是唯一可控、可读的方式
为什么 /sys/block/*/queue/ 里的东西和 workqueue 无关?
很多人搜到 /sys/block/sda/queue/nr_requests 就以为是在看 workqueue 状态,这是典型误解。这个目录下所有文件描述的是**块设备 I/O 请求队列(blk-mq 或 legacy elevator queue)**,属于 block layer,和 workqueue 完全不同层级。
-
nr_requests是设备驱动层向硬件提交的未完成 I/O 请求个数,和work_struct是否排队毫无关系 - workqueue 处理的是“内核函数延迟执行”,比如 SCSI 错误恢复、NVMe 控制器重置回调、USB 设备热插拔后配置等——它们可能最终触发 I/O,但本身不是 I/O 请求
- 混淆这两者会导致你盯着
nr_requests=0却发现kworkerCPU 占用很高,然后陷入排查误区
怎样安全地观察 workqueue 行为而不干扰系统?
别用 echo 1 > /sys/kernel/debug/tracing/events/workqueue/enable 这类 debugfs 开关,除非你在测试环境且清楚后果——开启后 trace 数据量极大,容易拖慢甚至卡死系统,尤其在高负载服务器上。
推荐做法是:
- 用
top -H或htop,过滤出kworker,观察其 CPU 使用率波动,结合时间点看是否与你触发的操作(如插拔 USB、重启网卡)同步 - 检查
dmesg -T | grep -i "work",内核日志里有时会打印 workqueue 相关警告,比如workqueue: pool 0: failed to create worker - 若写驱动,务必用
flush_work()或cancel_work_sync()而非裸 sleep,否则可能因 workqueue 调度延迟导致超时逻辑错乱
真正难的从来不是“怎么看到”,而是“看到之后怎么区分是正常调度还是资源耗尽”。比如 kworker/u8:3 长期占满一个 CPU 核,大概率不是 workqueue 本身问题,而是它执行的那个 func 函数卡在了自旋锁或无限循环里——这时候得顺着 stack 往上翻,而不是盯着队列长度。











