我是靠谱客的博主 怕黑萝莉,最近开发中收集的这篇文章主要介绍linux遍历子进程浅析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

最近在看《linux内核设计与实现》【陈莉君】,其中关于linux遍历子进程的叙述如下:

struct task_struct *task;
struct list_head *list;

list_for_each(list,&current->children)
{
    task=list_entry(list,structtask_struct,sibling);
}

初次阅读时感觉很不理解,后经细细琢磨,方知原来如此,下面是我个人的理解,以与诸君探讨。

1、进程亲属关系的成员

struct tast_struct {
    /* real parent process */
    struct task_struct *real_parent;
    /* recipient of SIGCHLD, wait4() reports */
    struct task_struct *parent;
    /* list of my children */
    struct list_head children;
    /* linkage in my parent's children list */
    struct list_head sibling;
    /* threadgroup leader */
    struct task_struct *group_leader;
}

2、linux内核的链表操作

/*------------------------------------------------
 * list_for_each(/include/linux/list.h)
 *----------------------------------------------*/
#define list_for_each(pos,head) 
for(pos=(head)->next; pos!=head;pos=pos->next)

/*------------------------------------------------
 * list_entry(/include/linux/list.h)
 *----------------------------------------------*/
#define list_entry(ptr, type, member) 
    container_of(ptr, type, member)

/*------------------------------------------------
 * container_of(include/linux/kernel.h)
 *----------------------------------------------*/
#define container_of(ptr, type, member) ({          
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    
    (type *)( (char *)__mptr - offsetof(type,member) );})

/*------------------------------------------------
 * offsetof(/include/linux/stddef.h)
 *----------------------------------------------*/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

3、下面来解释linux遍历子进程的原理

list_for_each(list,&current->children)
@list

是指向struct list_head类型的指针,故它可以指向进程描述符中的children或者sibling

@current

当前正在执行的进程

先对list_for_each宏做如下格式替换

#define list_for_each(list,head) 
for(list=(&current->children)->next; list!=&current->children; list=list->next)

再对list_entry进行宏替换

struct task_struct *task;
struct list_head *list;

list_for_each(list,&current->children)
{
    task=container_of(list,struct task_struct,sibling);
}

可以看到进程中的children和sibling有潜在的关系,我们再来看他们二者的关系。
在task_struct结构体中有对成员sibling的注释为
structlist_head sibling; // linkage in my parent’schildren list
直译过来是该指针存放本进程的父进程的子进程的list.
某网站上有段英文解释:

In order to organize data as linked list using struct
 list_head you have to declare list root and declare 
 the same type (struct list_head). children entry of struct task_struct entry is a root. sibling entry of 
sibling are used. Usage of list_for_each for children means what children is a root. Usage of list_entry for 
sibling means what sibling is a list entry.

该段的大意是指在一个循环链表中,children指向链表头,sibling指向链表的链表项。
Linux进程家族关系图如下
这里写图片描述

通过上述解说及图示理解,container_of定义中,首先将通过list_for_each获得的list_head类型的指针赋予一个临时定义的变量__mptr,存放了该子进程在父进程的子进程list中的位置,其实也就是该子进程的task_struct结构体中的sibling指针,而后通过offsetof获得偏移量之后,通过减法关系,即获得了该子进程的task_struct的指针。

最后

以上就是怕黑萝莉为你收集整理的linux遍历子进程浅析的全部内容,希望文章能够帮你解决linux遍历子进程浅析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部