プロセスグループ
Rev.2を表示中。最新版はこちら。
プロセスグループとスレッドグループを勘違いしておりました。複数のプロセスをまとめてプロセスグループというものが作られます。プロセスグループを作ると親となるプロセスグループにシグナルを送ると、そのグループのプロセスへもシグナルが送られます。httpdはpreforkで前もって複数のプロセス(スレッド)が立ち上がります。親のhttpdを削除すると、すべてのhttpdが削除されます。これは、これらのhttpdがプロセスグループを形成しているからです。
[root@localhost ~]# ps -fje | more UID PID PPID PGID SID C STIME TTY TIME CMD root 1 0 1 1 0 19:29 ? 00:00:04 init [3] root 72 7 1 1 0 19:29 ? 00:00:00 [kseriod] root 129 7 1 1 0 19:29 ? 00:00:00 [pdflush] root 130 7 1 1 0 19:29 ? 00:00:01 [pdflush] root 131 7 1 1 0 19:29 ? 00:00:00 [kswapd0] root 132 7 1 1 0 19:29 ? 00:00:00 [aio/0] root 290 7 1 1 0 19:29 ? 00:00:00 [kpsmoused] root 1511 1 1511 1511 0 19:31 ? 00:00:00 /usr/sbin/sshd root 1520 1 1520 1520 0 19:31 ? 00:00:00 /usr/sbin/httpd apache 1557 1520 1520 1520 0 19:31 ? 00:00:00 /usr/sbin/httpd apache 1558 1520 1520 1520 0 19:31 ? 00:00:00 /usr/sbin/httpd apache 1559 1520 1520 1520 0 19:31 ? 00:00:00 /usr/sbin/httpd apache 1560 1520 1520 1520 0 19:31 ? 00:00:00 /usr/sbin/httpdPPIDは親のプロセスIDをPGIDはプロセスグループ番号です。プロセスグループ番号は親プロセスのIDとなります。下から5つ目のhttpdのPID=1529,PGID=1529で、これがプロセスリーダだと分かります。下の4つのPGIDは1520,また親プロセスも1520ですから、プロセスグループを形成していて、しかもスレッドとして起動されたな。というのが分かります。
プロセスグループのカーネル実装は、do_forkからよばれるcopy_processでtask_struct構造体のpid_t tgidメンバーに設定し、struct list_head thread_groupでリスト化することで実現しています。なお、スレッドでない場合自プロセスIDを設定します。自分が親でグループなし。という感じです。
static struct task_struct *copy_process(unsigned long clone_flags,
・・・・・
p->pid = pid_nr(pid);
p->tgid = p->pid;
if (clone_flags & CLONE_THREAD)
p->tgid = current->tgid;
・・・・・
if (clone_flags & CLONE_THREAD) {
atomic_inc(¤t->signal->count);
atomic_inc(¤t->signal->live);
p->group_leader = current->group_leader;
list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
・・・・・
シグナル発生時、send_signal経由してよばれるcomplete_signal関数内で、スレッドグループに発生した致命的な(マスクできないってこと?)シグナルを、struct list_head thread_groupをたどることにより、全プロセス(スレッド)に配送しています。
static void complete_signal(int sig, struct task_struct *p, int group)
{
・・・・・
if (!sig_kernel_coredump(sig)) {
signal->flags = SIGNAL_GROUP_EXIT;
signal->group_exit_code = sig;
signal->group_stop_count = 0;
t = p;
do {
sigaddset(&t->pending.signal, SIGKILL);
signal_wake_up(t, 1);
} while_each_thread(p, t);
return;
・・・・・
}





