简介
Peeking into Linux kernel-land using /proc filesystem for quick’n’dirty troubleshooting
这篇文章也不会涉及内核调试器或者SystemTap脚本之类的东西,完全是最最简单地在有用的proc
文件系统节点上执行“cat /proc/PID/xyz”
这样的命令。
定位一个程序“运行缓慢”的问题
下面要举的这个例子是这样的:一个DBA反映说他们的find命令一直运行缓慢,
半天都没有什么输出,他们想知道这是为什么。
听到这个问题的时候我就大概有直觉造成这个问题的原因,但是他们还是想知道怎么系统地追踪这类问题,并找到解决方案。
首先,让我们看看find进程是否还在:
跑的好好的,PID是27288(请记好这个将会伴随整篇博客的数字)。
那么,我们就从最基础的开始分析它的瓶颈:如果它不是被什么操作卡住了(例如从cache中加载它所需要的内容),它应该是100%的CPU占用率;
如果它的瓶颈在IO或者资源竞争,那么它应该是很低的CPU占用率,或者是%0。
我们先看下top:
[root@oel6 ~]# top -cbp 27288
top - 11:58:15 up 7 days, 3:38, 2 users, load average: 1.21, 0.65, 0.47
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 2026460k total, 1935780k used, 90680k free, 64416k buffers
Swap: 4128764k total, 251004k used, 3877760k free, 662280k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27288 root 20 0 109m 1160 844 D 0.0 0.1 0:01.11 find . -type f
结果很清楚:这个进程的CPU占用率很低,几乎为零。
但是CPU占用低也分情况:一种是进程完全卡住了,根本没有机会获得时间片;
另一种是进程在不停进入等待的状态(例如poll动作就是时不时超时后,进程进入休眠状态)。
虽然这剩下的细节top还不足以完全给我们展示,但是至少我们知道了这个进程没有在烧CPU时间。
通常情况下,如果进程处于这种状态
(%0的CPU占用一般说明进程是卡在了某个系统调用,因为这个系统调用阻塞了,内核需要把进程放到休眠状态)
我都会用strace
跟踪一下这个进程具体卡在了哪个系统调用。
而且,如果进程不是完全卡住了,那进程中的系统调用情况也会在strace的输出中有所展示
(因为一般阻塞的系统调用会在超时返回后,过一段时间再进入阻塞等待的状态)。
让我们试试strace:
[root@oel6 ~]# strace -cp 27288
Process 27288 attached - interrupt to quit
^C
^Z
[1]+ Stopped strace -cp 27288
[root@oel6 ~]# kill -9 %%
[1]+ Stopped strace -cp 27288
[root@oel6 ~]#
[1]+ Killed strace -cp 27288
尴尬,strace自己也卡住了!半天没有输出,也不响应Ctrl-C,我不得不通过Ctrl-Z把它扔到后台再杀掉它。想简单处理还真是不容易啊。
那只好再试试pstack了(Linux上的pstack只是用shell脚本包了一下GDB)。
尽管pstack看不到内核态的内容,但是至少它能告诉我们是哪个系统调用最后执行的
(通常pstack输出的用户态调用栈最顶部是一个libc库的系统调用):