据我了解,进程描述符存储在双向链表数据结构中。但fork
可以用来为同一个进程创建多个子进程,这让我觉得存在一种树结构,因为多个进程会指向一个父进程。哪个是对的?进程描述符与进程有什么不同吗?
答案1
fork()
通过复制进程描述符来创建一个新进程。因此,这两个进程确实共享(至少在最初)一些数据,但是一旦一个进程启动改变它的写时复制机制确保更改仅本地化到实际进行更改的进程。它是 UNIX 上进程生成的标准机制。
这当然在进程之间创建了一种相当自然的父子关系,但这与内核中的内部表示无关。进程描述符可以被实现为链表、树、哈希表或任何其他(或多或少)合适的结构。真正需要的只是放置在指向父进程(也可能还有子进程)的内核进程描述符中。是否将其用作结构的关键部分是设计决策。在决定这样的事情时,要考虑的许多事情之一是,例如,一旦父进程退出就会发生什么——在 UNIX 上,进程init
采用孤立进程(及其所有子进程)。
答案2
您的困惑源于混合两件事:(1)保持进程描述符的组织,以及(2)父/子关系。
您不需要父/子关系来决定接下来运行哪个进程,或者(通常)向哪个进程传递信号。因此,Linux task_struct
(我linux/sched.h
在 3.11.5 内核源代码中找到)具有:
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */
/*
* children/sibling forms the list of my natural children
*/
struct list_head children; /* list of my children */
struct list_head sibling; /* linkage in my parent's children list */
你是对的,存在一个用于子/父关系的树结构,但它似乎隐藏在另一个列表中,并且有一个指向父项的指针。
著名的双向链表在 3.11.5struct task_struct
结构定义中并不明显。如果我正确地阅读了代码,则未注释的结构元素struct list_head tasks;
是“组织”双向链表,但我可能是错的。