Mic*_*ael 1 c linux system-calls ps procfs
我正在尝试实现我自己的ps命令,称为psmod.我可以使用linux系统调用和/proc目录的所有实用程序.
我发现目录中的所有目录都/proc以数字作为名称,是系统中的进程.我的问题是:如何只选择那些在psmod被调用时处于活动状态的进程?我知道/proc/<pid>/stat有一封信代表了这个过程的现状; 无论如何,对于每一个进程来说/proc,这封信就是S在睡觉.
我还试图向每个进程发送一个信号0,从0到maximumnumberofprocesses(在我的例子中,32768),但是这样它发现的进程远远多于进程中的进程/proc.
所以,我的问题是,ps工作怎么样?源码对我来说有点复杂,所以如果有人能解释我,我将不胜感激.
ps如何工作?
学习标准工具的方法是检查他们的源代码.有几种实现ps:procps和busybox; 而busybox更小,从它开始会更容易.ps来自busybox的来源:http: //code.metager.de/source/xref/busybox/procps/.主循环来自ps.c:
632 p = NULL;
633 while ((p = procps_scan(p, need_flags)) != NULL) {
634 format_process(p);
635 }
Run Code Online (Sandbox Code Playgroud)
实现procps_scan是procps.c(ENABLE_FEATURE_SHOW_THREADS首次忽略来自ifdefs 内部的代码).首先调用它将/proc使用alloc_procps_scan()以下命令打开目录:
290 sp = alloc_procps_scan();
100 sp->dir = xopendir("/proc");
Run Code Online (Sandbox Code Playgroud)
然后procps_scan将从/proc目录中读取下一个条目:
292 for (;;) {
310 entry = readdir(sp->dir);
Run Code Online (Sandbox Code Playgroud)
从子目录名解析pid:
316 pid = bb_strtou(entry->d_name, NULL, 10);
Run Code Online (Sandbox Code Playgroud)
并阅读/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);
Run Code Online (Sandbox Code Playgroud)
实际的无条件打印是format_process,ps.c.
因此,busybox的简单ps将读取所有进程的数据,并将打印所有进程(如果有-T选项,则打印所有进程和所有线程).
如何在调用psmod时仅选择那些处于活动状态的进程?
什么是"活跃"?如果要查找存在的所有进程,请执行readdir /proc.如果您只想找到非睡眠,请完整阅读/proc,检查每个过程的状态并仅打印非睡眠状态.该/procFS是虚拟的,是它相当快.
PS:例如,普通ps程序只打印当前终端的进程,通常是两个:
$ ps
PID TTY TIME CMD
7925 pts/13 00:00:00 bash
7940 pts/13 00:00:00 ps
Run Code Online (Sandbox Code Playgroud)
但我们可以用strace它,strace -ttt -o ps.log ps我看到它ps确实读取每个进程目录,文件stat和status.并且所需的时间(-ttstrace的选项给我们每个系统调用的时间戳):XX.719011 - XX.870349或仅在strace下120毫秒(这会减慢所有系统调用).根据time ps(我总共有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
Run Code Online (Sandbox Code Playgroud)