我是靠谱客的博主 怕黑萝莉,这篇文章主要介绍linux遍历子进程浅析,现在分享给大家,希望可以做个参考。

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

复制代码
1
2
3
4
5
6
7
struct task_struct *task; struct list_head *list; list_for_each(list,&current->children) { task=list_entry(list,structtask_struct,sibling); }

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

1、进程亲属关系的成员

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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内核的链表操作

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*------------------------------------------------ * 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宏做如下格式替换

复制代码
1
2
#define list_for_each(list,head) for(list=(&current->children)->next; list!=&current->children; list=list->next)

再对list_entry进行宏替换

复制代码
1
2
3
4
5
6
7
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.
某网站上有段英文解释:

复制代码
1
2
3
4
5
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遍历子进程浅析内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部