busybox/procps/ps.c
busybox/libbb/procps.c
我們在串口終端通過ps命令查看系統當前正在運行的進程:
~ # ps
PID USER VSZ STAT COMMAND
1 root 1080 S init
2 root 0 SW [kthreadd]
3 root 0 SW [ksoftirqd/0]
4 root 0 SW [kworker/0:0]
5 root 0 SW< [kworker/0:0H]
6 root 0 SW [kworker/u2:0]
7 root 0 SW [rcu_preempt]
8 root 0 SW [rcu_bh]
9 root 0 SW [rcu_sched]
10 root 0 SW< [khelper]
11 root 0 SW< [writeback]
12 root 0 SW< [bioset]
13 root 0 SW< [kblockd]
14 root 0 SW [khubd]
15 root 0 SW [kworker/0:1]
16 root 0 SW< [cfg80211]
17 root 0 SW< [rpciod]
18 root 0 SW [kswapd0]
19 root 0 SW< [nfsiod]
20 root 0 SW< [cifsiod]
21 root 0 SW< [crypto]
34 root 0 SW< [dwc_otg]
35 root 0 SW [kworker/u2:1]
54 root 0 SW< [deferwq]
55 root 0 SW [kworker/0:2]
56 root 0 SW< [kworker/0:1H]
233 root 0 SWN [jffs2_gcd_mtd3]
238 root 1080 S syslogd
240 root 1072 S klogd
241 root 1084 S -/bin/sh
242 root 1080 R ps
720 puts(" PID USER VSZ STAT COMMAND");
在busybox/procps/ps.c文件中ps_main函數,是與ps命令的第一行輸出對應的。
procps_status_t *p;
728 while ((p = procps_scan(p, psscan_flags)) != NULL) {
...
781 const char *user = get_cached_username(p->uid);
782 len = printf("%5u %-8.8s %s %s ",
783 p->pid, user, buf6, p->state);
...
787 {
788 int sz = terminal_width - len;
789 char buf[sz + 1];
790 read_cmdline(buf, sz, p->pid, p->comm);
791 puts(buf);
792 }
}
先看p = procps_scan(p, psscan_flags),這個函數在busybox/libbb/procps.c中實現,每一個進程都會在/proc目錄下新建一個進程號對應的文件夾,這個函數通過讀取/proc目錄下所有進程號對應的文件夾,讀取文件夾下的stat, cmdline等文件,並將讀取的這些文件的信息保存在procps_status_t* sp這個結構體裡面並返回這個結構體。
再看get_cached_username函數,他根據procps_scan函數返回的procps_status_t* p指針中的p->uid來返回進程的用戶名,然後下一行的printf打印出了PID USER VSZ STAT這些字段的信息都是從指針p中獲取。
最後再看read_cmdline這個函數,他會讀取執行程序的命令並復制到buf中,讓下一行的puts打印出來。如果進程占用的VSZ為0,那麼他會在程序對應的命令的兩邊加上’[ ]’,比如dwc_otg,khubd這些進程由於VSZ都是0,所以在他們的兩邊都有’[ ]’。
最後要說一句,不管是內核創建的進程還是用戶空間創建的進程都會在/proc目錄下新建一個進程號對應的文件夾,所以都會通過ps顯示出來。