linux遍历子进程浅析
2016-06-20 22:30
766 查看
最近在看《linux内核设计与实现》【陈莉君】,其中关于linux遍历子进程的叙述如下:
初次阅读时感觉很不理解,后经细细琢磨,方知原来如此,下面是我个人的理解,以与诸君探讨。
@list
是指向struct list_head类型的指针,故它可以指向进程描述符中的children或者sibling
@current
当前正在执行的进程
先对list_for_each宏做如下格式替换
再对list_entry进行宏替换
可以看到进程中的children和sibling有潜在的关系,我们再来看他们二者的关系。
在task_struct结构体中有对成员sibling的注释为
structlist_head sibling; // linkage in my parent’schildren list
直译过来是该指针存放本进程的父进程的子进程的list.
某网站上有段英文解释:
该段的大意是指在一个循环链表中,children指向链表头,sibling指向链表的链表项。
Linux进程家族关系图如下
通过上述解说及图示理解,container_of定义中,首先将通过list_for_each获得的list_head类型的指针赋予一个临时定义的变量__mptr,存放了该子进程在父进程的子进程list中的位置,其实也就是该子进程的task_struct结构体中的sibling指针,而后通过offsetof获得偏移量之后,通过减法关系,即获得了该子进程的task_struct的指针。
struct task_struct *task; struct list_head *list; list_for_each(list,¤t->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,¤t->children)@list
是指向struct list_head类型的指针,故它可以指向进程描述符中的children或者sibling
@current
当前正在执行的进程
先对list_for_each宏做如下格式替换
#define list_for_each(list,head) \ for(list=(¤t->children)->next; list!=¤t->children; list=list->next)
再对list_entry进行宏替换
struct task_struct *task; struct list_head *list; list_for_each(list,¤t->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 socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程