kworker 是什么
kworker 是内核工作队列(workqueue)的通用工作线程,负责执行被推迟处理的内核任务:块设备 IO 完成、文件系统回写、部分网络协议栈处理、驱动事件等。它本身不做业务计算,单个 kworker 长期占满一个核,通常说明某个子系统在持续投递工作,排查方向是顺着线程名与内核栈找到投递方,而不是限制 kworker 自身。
基本信息
| 查看现状 | ps -eo pid,psr,pcpu,comm | grep kworker |
|---|---|
| 命名规律 | kworker/<cpu>:<序号> 为 per-CPU 线程;kworker/uN:M 为 unbound 线程 |
| 下钻栈 | cat /proc/<pid>/stack(需 root) |
| 热点定位 | perf record -ag 后按 comm 过滤 kworker |
| 旁证 | dmesg -T 看驱动/IO 报错,/proc/pressure/io 看停顿比例 |
| 内部视图 | debugfs 下的 workqueue 信息(随内核版本与配置而定) |
典型使用场景
- 高磁盘写回负载:dirty 页回写让 kworker 持续占用部分核,属于正常但需要评估影响
- 网络密集场景:协议栈延迟处理与网卡驱动工作,常与软中断同时升高
- 驱动问题排查:某个 kworker 长时间不降且伴随 dmesg 报错,指向设备或驱动缺陷
- 「某个核一直是 100%,但 top 里没有业务进程」这类现象的解释与定位
- 隔离核场景验证:确认 kworker 是否跑到了本应留给业务的独占核上
定位步骤
定位步骤
ps -eo pid,psr,pcpu,stat,comm --sort=-pcpu | grep kworker | head # psr 是它当前所在的核
sudo cat /proc/<kworker_pid>/stack # 看此刻卡在哪个内核函数,判断归属子系统
sudo perf record -ag -e cycles -- sleep 10 # 系统级采样 10 秒
sudo perf report --stdio | grep -m20 kworker # 在报告里过滤出 kworker 的调用栈
dmesg -T | tail -50 # 检查是否有驱动、IO 超时、EXT4 之类报错
cat /proc/pressure/io # 若指向 IO,用 PSI 量化停顿比例再决定是否调 vm.dirty*名字怎么读
| 名字形态 | 含义 | 排查提示 |
|---|---|---|
| kworker/3:2 | per-CPU 工作线程,数字是所属 CPU | 被固定在那个核上,所以常见单核打满 |
| kworker/u16:5 | unbound 线程,可在多个核间迁移 | 与具体 CPU 无关,要看整体工作队列积压 |
| kworker/R-xxx | 为特定工作队列创建的救援线程 | 出现往往意味着该队列工作项积压严重 |
| ksoftirqd/3 | 软中断线程,不是 kworker | 名字相近但成因是软中断,处理方式不同 |
per-CPU 的 kworker 绑定在名字里那个 CPU 上,所以「只有一个核被吃满」是常见形态;unbound 线程才会随调度迁移。看到单核打满时先读名字里的编号,再决定要不要调整中断或绑定策略。
kworker 属于内核线程,不受业务 cgroup 的 CPU 限额约束。业务容器里看不到宿主的 kworker 线程,需要从宿主机视角排查;反过来,宿主看到的高占用也不能靠给容器加限额解决。