实现我自己的ps命令

时间:2014-05-12 11:37:55

标签: c linux system-calls ps procfs

我正在尝试实现自己的ps命令,名为psmod。 我可以使用linux系统调用和/proc目录的所有实用程序。

我发现/proc目录中的所有目录都有一个数字作为系统中的进程。我的问题是:如何在调用psmod时仅选择那些处于活动状态的进程? 我知道在/proc/<pid>/stat中有一封信代表了这个过程的现状;无论如何,对于/proc中的每个进程,这封信都是S,正在睡觉。

我还尝试向每个进程发送一个信号0,从0到maximumnumberofprocesses(在我的情况下,32768),但是这样它发现的进程远远多于{{1}中出现的进程。 }。

所以,我的问题是,/proc如何运作?源码对我来说有点复杂,所以如果有人能解释我,我将不胜感激。

2 个答案:

答案 0 :(得分:6)

  

ps如何运作?

学习标准工具的方法 - 检查他们的源代码。 psprocps和busybox有多种实现方式;而busybox更小,从它开始会更容易。来自busybox的ps来源:http://code.metager.de/source/xref/busybox/procps/。主loop from ps.c

632 p = NULL;
633 while ((p = procps_scan(p, need_flags)) != NULL) {
634     format_process(p);
635 }

procps_scan的实施位于procps.c(第一次忽略来自ENABLE_FEATURE_SHOW_THREADS ifdef内部的代码)。首次调用它将使用/proc打开alloc_procps_scan()目录:

290     sp = alloc_procps_scan();

100 sp->dir = xopendir("/proc");

然后procps_scan将读取/proc目录中的下一个条目:

292 for (;;) {
310     entry = readdir(sp->dir);

从子目录名解析pid:

316     pid = bb_strtou(entry->d_name, NULL, 10);

并阅读/prod/pid/stat

366     /* These are all retrieved from proc/NN/stat in one go: */
379         /* see proc(5) for some details on this */
380         strcpy(filename_tail, "stat");
381         n = read_to_buf(filename, buf);

实际无条件打印位于format_process, ps.c

因此,busybox的简单ps将读取所有进程的数据,并将打印所有进程(如果有-T选项,则打印所有进程和所有线程。)

  

如何只调用那些在调用psmod时处于活动状态的进程?

什么是&#34;活跃&#34;?如果要查找存在的所有进程,请执行/proc的readdir。如果您只想找到非睡眠状态,请完整阅读/proc,检查每个进程的状态并仅打印非睡眠状态。 /proc fs是虚拟的,而且速度相当快。

PS:例如,普通ps程序只打印当前终端的进程,通常是两个:

$ ps
  PID TTY          TIME CMD
 7925 pts/13   00:00:00 bash
 7940 pts/13   00:00:00 ps

但我们可以strace strace -ttt -o ps.log ps ps,我看到stat确实读取了每个进程目录,文件status-tt。并且所需的时间(选项time ps strace给出了每个系统调用的时间戳):XX.719011 - XX.870349或仅在strace下120毫秒(这会减慢所有系统调用)。根据{{​​1}}(我总共有250个进程),现实生活中只需要20毫秒:

$ time ps
  PID TTY          TIME CMD
 7925 pts/13   00:00:00 bash
 7971 pts/13   00:00:00 ps

real    0m0.021s
user    0m0.006s
sys 0m0.014s

答案 1 :(得分:-3)

“我的问题是:如何只选择那些在调用psmod时处于活动状态的进程?”

我希望这个命令可以帮到你:

top -n 1 | awk“NR&gt; 7”| awk {'print $ 1,$ 8,$ 12'} | grep R

我在ubuntu 12上。