摘要:凌晨三点的监控告警划破平静——生产服务器CPU使用率突然飙升至100%,但登录系统后执行top命令,所有用户态进程CPU占用加起来不足10%。这种"幽灵般"的CPU占用,往往是内核线程在作祟。内核线程作为操作系统的"幕后工作者",负责处理中断、内存回收等核心任
凌晨三点的监控告警划破平静——生产服务器CPU使用率突然飙升至100%,但登录系统后执行top命令,所有用户态进程CPU占用加起来不足10%。这种"幽灵般"的CPU占用,往往是内核线程在作祟。内核线程作为操作系统的"幕后工作者",负责处理中断、内存回收等核心任务,它们不像用户态进程那样有明显的命令名,甚至可能隐藏在[kworker/0:1]这样的括号名称中,成为监控工具的"漏网之鱼"。
要抓住这些"隐形刺客",需要一套超越常规工具的"侦探装备"。本文将通过实战案例,带你掌握pidstat、perf和eBPF这三大工具,一步步揭开内核线程的神秘面纱。
常规top命令的盲区在于默认不显示线程级信息,而内核线程的CPU占用往往分散在多个线程中。此时pidstat(sysstat工具集成员)就是你的"放大镜",它能穿透进程层级,直接显示线程CPU占用。
03:45:27 PM UID TGID TID %usr %system %guest %CPU CPU Command 03:45:28 PM 0 - 12345 0.00 99.99 0.00 99.99 0 |__kworker/0:1 %system接近100%:说明线程在内核态疯狂工作Command为[kworker/0:1]:典型的内核工作队列线程,负责处理异步任务图1:pidstat输出显示kworker线程占用99%内核态CPU
通过pidstat,我们锁定了可疑内核线程TID(如12345),但还需进一步定位它在执行什么任务。
pidstat告诉我们"谁在占用CPU",而perf工具能回答"在做什么"。作为linux内核原生性能分析工具,perf可通过硬件计数器采样,生成函数调用栈,配合火焰图直观展示内核函数热点。
记录系统级CPU调用栈,持续10秒:sudo perf record -a -g -- sleep 10-a:监控所有CPU核心-g:记录函数调用栈sleep 10:采样时长生成火焰图(需安装FlameGraph工具):git clone https://github.com/brendangregg/FlameGraph.git perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > cpu_flame.svg打开cpu_flame.svg,x轴宽度代表函数执行时间占比,y轴代表调用栈深度。若看到kworker线程对应的栈顶函数为__sbitmap_queue_get或ext4_free_inode,则可能是文件系统或驱动模块在频繁触发内核任务。
图2:火焰图显示kworker线程大量调用ext4文件系统相关函数
通过火焰图,我们发现CPU被ext4_free_inode函数占用——这是ext4文件系统回收inode的内核函数,可能由频繁删除小文件触发。
当perf火焰图指向内核模块或驱动时,ebpf(扩展伯克利包过滤器)就是"手术刀"级工具。它能动态注入内核代码,追踪函数参数、返回值,甚至修改内核行为(需谨慎)。以排查kworker任务为例,我们用bpftrace编写一行脚本即可追踪任务来源。
kworker PID: 12345, Function: ext4_free_inode kworker PID: 12345, Function: __sbitmap_queue_get结合perf火焰图,可确认kworker正在处理ext4文件系统的inode回收,而根源是某业务进程在短时间内删除了10万+小文件,触发内核异步清理任务。
图3:eBPF工作流程:用户态编写程序→内核验证器→JIT编译→事件触发执行
内核线程导致的CPU 100%问题,本质是"用户态监控工具"与"内核态行为"之间的信息差。通过pidstat穿透线程层级、perf解析内核调用栈、eBPF动态追踪任务来源,我们能一步步揭开"隐形刺客"的面纱。记住:当top显示一切正常时,问题往往藏在内核的汪洋大海中,而掌握这三个工具,你就拥有了遨游内核的罗盘。
来源:祁丶祁一点号