プロセス親子関係のリスト
Rev.2を表示中。最新版はこちら。
各プロセスには親子/兄弟関係にあるプロセスのリストを有しています。それがsibling/childrenメンバーです。LINUX詳解にはプロセスの親子関係を以下のような感じの図表があって(P0がP1/P2/P3を作成し、P3がP4を作成します。)、てっきり最初の子プロセスがchildrenにリストされて、それ以降のプロセスは最初に作成されて子プロセスのsiblingをヘッドとしてリストされていくものと思っていて、それならchildrenはstruct list_headで有る必要がないのではと思っていました。子プロセスはchildrenをヘッダとするリストに、siblingを項目として繋げていくということです。従ってP1/P2は子プロセスを有していない故、children->prev/nextは自分自身を示しています。
P0
(children)<-------------------
| |
P1 P2 P3
(sibling)--->(sibling)--->(sibling)
(children)
|
(children)
P4
p->real_parentはP0に相当します。そのchildrenにlist_add_tailマクロで子プロセスのsiblingを繋いでいます。そしてスレッドグループリーダなら(通常のプロセスはスレッドグループリーダです。)、新規にPIDネームスペースを作成したなら、そのネームスペースの元親としてこのプロセスをセットします。これは子プロセスの親が削除され、その親プロセスを繋ぎ換えなければならない時に参照されます。attach_pid関数でPIDTYPE_PGID/PIDTYPE_SIDのリンクノードを、親の該当するstruct pid にリストします。init_task.tasksにはPIDTYPE_PGID/PIDTYPE_SIDのタイプに関係なく、スレッドグループリーダのプロセスは全てリストされているということです。
static struct task_struct *copy_process(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *child_tidptr,
struct pid *pid,
int trace)
:
if (likely(p->pid)) {
list_add_tail(&p->sibling, &p->real_parent->children);
tracehook_finish_clone(p, clone_flags, trace);
if (thread_group_leader(p)) {
if (clone_flags & CLONE_NEWPID)
p->nsproxy->pid_ns->child_reaper = p;
p->signal->leader_pid = pid;
p->signal->tty = current->signal->tty;
set_task_pgrp(p, task_pgrp_nr(current));
set_task_session(p, task_session_nr(current));
attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
attach_pid(p, PIDTYPE_SID, task_session(current));
list_add_tail_rcu(&p->tasks, &init_task.tasks);
__get_cpu_var(process_counts)++;
}
attach_pid(p, PIDTYPE_PID, pid);
nr_threads++;
}
:
}・補足
プロセスIDからstruct task_structを取得する場合、init_task.tasksを走査することで検索しません。struct pid をハッシュしているテーブルから検索します。





