プロセス親子関係のリスト


各プロセスには親子/兄弟関係にあるプロセスのリストを有しています。それがsibling/childrenメンバーです。LINUX詳解にはプロセスの親子関係を以下のような感じの図表があって(P0がP1/P2/P3を作成し、P3がP4を作成します。)、てっきり最初の子プロセスがchildrenにリストされて、それ以降のプロセスは最初に作成されて子プロセスのsiblingをヘッドとしてリストされていくものと思っていて、それならchildrenはstruct list_headで有る必要がないのではと思っていました。

子プロセスはchildrenをヘッダとするリストに、siblingを項目として繋げていくということです。従ってP1/P2は子プロセスを有していない故、children->prev/nextは自分自身を示しています。要はchildrenは繋がれる項目で、siblingは繋ぐ項目というところです。
     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)
 :
      p->group_leader = p;
      if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
               p->real_parent = current->real_parent;
               p->parent_exec_id = current->parent_exec_id;
       } else {
               p->real_parent = current;
               p->parent_exec_id = current->self_exec_id;
       }
       if (clone_flags & CLONE_THREAD) {
                p->group_leader = current->group_leader;
               list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
       }

       if (likely(p->pid)) {
               list_add_tail(&p->sibling, &p->real_parent->children);

               if (thread_group_leader(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++;
       }
   :
}
たぶんこんな感じになるのではと思います。(CLONE_THREDからCLONE_THREDを作成した場合は・・・。)

・補足
プロセスIDからstruct task_structを取得する場合、init_task.tasksを走査することで検索しません。struct pid をハッシュしているテーブルから検索します。


最終更新 2011/05/25 01:02:39 - north
(2011/05/16 00:58:32 作成)
添付ファイル
children.JPG - north
children1.JPG - north


検索

アクセス数
3697963
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。