遍历内核所有的进程
我们知道linux系统中的初始话进程为init_task,内核在初始化后期以该构造进程为原型,创建了用户空间的进程树的根init,和内核空间线程树的根kthreadd,用pstree只能显示init树结构。
那么linux内核中如何得到,系统中所有进程列表呢?
1 按照进程task_struct中组成的血缘关系,来遍历这两个根,这种方式是树状遍历方式,也是最传统简单方式
下面将init进程传进去后,即可遍历该进程下所有的子进程
159 static void getLeakingThreads(struct task_struct* root)
160 {
161 struct list_head* list;
162 struct task_struct* curr;
163 //printk("Line:%d, Function:%s,task_name:%s\n",__LINE__,__FUNCTION__,root->comm);
164 list_for_each(list,&root->children) //while list != root->children
165 {
166 curr = list_entry(list,struct task_struct,sibling);
167
168 //if(strstr(detectedProcessBlackList,curr->comm))
169 insertList(curr,getProcessPss(curr));
170 getLeakingThreads(curr);
171 }
172 //printk("Line:%d, Function:%s\n",__LINE__,__FUNCTION__);
173 }
2 线性遍历方式访问所有进程
7 struct task_struct* p;
8 for_each_process(p)
9 printk("%s\n",p->comm);
这种方式实现原理如下:
#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
显然上述两种方式都是利用了task_struct结构中的连接关系实现,第二种按照进程创建的顺序遍历,第一种按照亲情关系遍历
3 在上篇博客中介绍了proc每进程目录的实现,其实现过程并非第二种,而是接下来第三种,经过测试,结果和第二种一致,也是按照进程创建顺序遍历进程列表
1 #include <linux/init.h>
2 #include <linux/pid.h>
3 #include <linux/module.h>
4 #include <linux/sched.h>
5 #include <linux/pid_namespace.h>
6 MODULE_LICENSE("GPL");
7 struct tgid_iter
8 {
9 unsigned int tgid;
10 struct task_struct* task;
11 };
12 typedef struct tgid_iter (*next_tgid) (struct pid_namespace *ns, struct tgid_iter iter);
13 static int __init in(void)
14 {
15 struct tgid_iter iter;
16 struct pid_namespace * ns = &init_pid_ns;
17 iter.task = NULL;
18 iter.tgid = 0;
19 if(!ns)
20 {
21 printk("%s\n","null");
22 return 0;
23 }
24 for(iter = ((next_tgid)0xc01fe1b0)(ns,iter);iter.task;iter.tgid +=1,iter = ((next_tgid)0xc01fe1b0)(ns,iter))
25 printk("%s\n",iter.task->comm);
26 return 0;
27 }
这种方式遍历进程号命名空间位图,该位图数组里描述了当前存在的所有进程
4 验证:
2、3输出结果一致,如下图所示:
root@ubuntu:/media/Kingston/Graduation/coding/other/getEveryProcess# dmesg -c|nl
1 [104330.912671] init
2 [104330.912685] kthreadd
3 [104330.912687] migration/0
4 [104330.912689] ksoftirqd/0
5 [104330.912690] watchdog/0
6 [104330.912691] events/0
7 [104330.912693] khelper
8 [104330.912694] kstop/0
9 [104330.912695] kintegrityd/0
10 [104330.912697] kblockd/0
11 [104330.912698] kacpid
12 [104330.912699] kacpi_notify
.......
113 [104330.912850] usb-storage
114 [104330.912852] hald-addon-stor
115 [104330.912853] make
116 [104330.912854] insmod
但是通过加入时间测试,发现方法2大约需要220us左右,而方法3大约需要210us左右
这3中方法的代码实现见附件