fork()
プロセス記述子をコピーして新しいプロセスを作成します。したがって、2 つのプロセスは (少なくとも最初は) 一部のデータを共有しますが、一方のプロセスが変更を開始するとすぐに変更します。 つまり、コピー オン ライト メカニズムにより、実際に変更を行ったプロセスのみに変更がローカライズされます。これは、UNIX でプロセスを生成するための標準的なメカニズムです。
もちろん、これによりプロセス間にかなり自然な親子関係が作成されますが、これはカーネルの内部表現とは無関係です。プロセス記述子は、リンクされたリスト、ツリー、ハッシュ テーブル、またはその他の (多かれ少なかれ) 適切な構造として実装できます。本当に必要なのは、親プロセス (および場合によっては子プロセスも) を指すカーネル プロセス記述子に配置することだけです。構造の重要な部分として使用するかどうかは、設計上の決定です。このようなことを決定する際に関係する多くのことの 1 つは、たとえば、親プロセスが終了するとどうなるかです。UNIX では init
プロセスは、孤立したプロセスを (すべての子プロセスと共に) 採用します。
あなたの混乱は、(1) プロセス記述子を整理しておくことと、(2) 親子関係の 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.5 struct task_struct
では明らかではありません 構造定義。コードを正しく読むと、コメント解除された構造体要素 struct list_head tasks;
は「編成」二重リンク リストですが、間違っている可能性があります。