私が理解したところ、プロセス記述子は二重接続リストデータ構造に格納されます。ただし、fork
同じプロセスに対して複数のサブプロセスを作成するために使用できます。複数のプロセスが親プロセスを指すので、ツリー構造があると考えることになります。どちらが正しいですか?プロセス記述子はプロセスとは異なりますか?
答え1
fork()
プロセス記述子をコピーして新しいプロセスを作成します。したがって、両方のプロセスは(少なくとも最初は)いくつかのデータを共有しますが、一度プロセスが開始されると変化記録中にコピーメカニズムにより、変更が実際に変更されたプロセスに限定されます。これはUNIXでプロセスを作成するための標準的なメカニズムです。
もちろん、これはプロセス間でかなり自然な親子関係を生成しますが、カーネルの内部表現とは何の関係もありません。プロセス記述子は、リンクリスト、ツリー、ハッシュテーブル、または他の(やや)適切な構造で実装することができる。実際に必要なのは、親プロセス(および子プロセスも可能)を指すカーネルプロセス記述子に配置することです。これを構造として使用するかどうかの重要な部分は設計決定です。そのような決定を下す際に考慮すべき多くの事項の1つは、例えば、親プロセスが終了したときに何が起こるかである。 UNIXでは、プロセスはinit
孤児(およびすべての子プロセス)になります。
答え2
混乱は、(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 */
あなたは正しいです。子/親関係のツリー構造がありますが、親へのポインタを持つ他のリストに隠されているようです。
有名な二重接続のリストは、struct task_struct
3.11.5 構造定義では明確ではない。コードを正しく読んでいる場合、コメントアウトされていない構造体要素struct list_head tasks;
は「構成」二重接続リストですが、間違っている可能性があります。