背景
在执行top
/ps
命令的时候,在COMMAND
一列,我们会发现,有些进程名被[]
括起来了,例如
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1542 928 root R 1064 2% 5% top
1 0 root S 1348 2% 0% /sbin/procd
928 1 root S 1060 2% 0% /bin/ash --login
115 2 root SW 0 0% 0% [kworker/u4:2]
6 2 root SW 0 0% 0% [kworker/u4:0]
4 2 root SW 0 0% 0% [kworker/0:0]
697 2 root SW 0 0% 0% [kworker/1:3]
703 2 root SW 0 0% 0% [kworker/0:3]
15 2 root SW 0 0% 0% [kworker/1:0]
27 2 root SW 0 0% 0% [kworker/1:1]
本文除了探索top中[]
的含义外,更重要的是,我们如何从仅有的信息定位到问题?
从应用代码到内核代码,授人以鱼不如授人以渔,你觉得呢?
对分析过程不感兴趣的童鞋,可以直接跳转到结论
应用代码逻辑分析
关键字:COMMAND
获取busybox的源码后,试试简单粗暴的检索关键字
[GMPY@12:22 busybox-1.27.2]$grep "COMMAND" -rnw *
结果发现,太多匹配的数据
applets/usage_pod.c:79: printf("=head1 COMMAND DESCRIPTIONS
");
archival/cpio.c:100: --rsh-command=COMMAND Use remote COMMAND instead of rsh
docs/BusyBox.html:1655:<p>which [COMMAND]...</p>
docs/BusyBox.html:1657:<p>Locate a COMMAND</p>
docs/BusyBox.txt:93:COMMAND DESCRIPTIONS
docs/BusyBox.txt:112: brctl COMMAND [BRIDGE [INTERFACE]]
docs/BusyBox.txt:612: ip ip [OPTIONS] address|route|link|neigh|rule [COMMAND]
docs/BusyBox.txt:614: OPTIONS := -f[amily] inet|inet6|link | -o[neline] COMMAND := ip addr
docs/BusyBox.txt:1354: which [COMMAND]...
docs/BusyBox.txt:1356: Locate a COMMAND
......
此时我发现,第一次匹配时因为存在大量非源码文件,所以显得很多,那么我能不能只检索C文件呢?
[GMPY@12:25 busybox-1.27.2]$find -name "*.c" -exec grep -Hn --color=auto "COMMAND" {} ;
这次结果只有71行,简单扫了下匹配的文件,有个有意思的发现
......
./shell/ash.c:9707: if (cmdentry.u.cmd == COMMANDCMD) {
./editors/vi.c:1109: // get the COMMAND into cmd[]
./procps/lsof.c:31: * COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
./procps/top.c:626: " COMMAND");
./procps/top.c:701: /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */
./procps/top.c:841: strcpy(line_buf, HDR_STR " COMMAND");
./procps/top.c:854: /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */
./procps/ps.c:441: { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM },
......
在busybox中,每一个命令都是单独一个文件,这代码逻辑结构好,我们直接进入procps/top.c文件626行
函数:display_process_list
procps/top.c的626行属于函数display_process_list,简单看一下代码逻辑
static NOINLINE void display_process_list(int lines_rem, int scr_width)
{
......
/* 打印表头 */
printf(OPT_BATCH_MODE ? "%.*s" : "