遍历内核所有的进程

     我们知道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中方法的代码实现见附件

posted on 2012-04-04 20:36  周健  阅读(3249)  评论(1编辑  收藏  举报

导航