プロセスグループ
プロセスグループ (Process Group) とは、POSIX準拠のオペレーティングシステムにおいて、1個以上のプロセスの集まりを意味する。この集まりはプロセスグループリーダーとなっているプロセスのプロセスIDと同じ値をプロセスグループIDとして識別に使用する。
プロセスグループはシグナルを複数のプロセスに配布するために使用される。killシステムコールはシグナルを個々のプロセスに送るだけでなく、プロセスグループに送ることもできる。プロセスグループに向けられたシグナルは、そのグループのメンバーである全プロセスに送られる。
プロセスグループへのシグナル送信は、シェルプログラムが使用するジョブコントロールの基本となっている。ttyデバイスドライバは、キーボードからの割り込みを契機としてフォアグラウンドのプロセスグループに SIGTSTP、SIGQUIT、SIGINTというシグナルを送る。また、フォアグラウンドでないプロセスグループが端末からの入力待ち状態(また、適切なフラグが設定されていれば表示待ち状態も)になっている場合にSIGTTINシグナルやSIGTTOUシグナルを送る。シェル(ひいてはその操作者)はコマンドパイプラインからプロセスグループを生成し、どのプロセスグループが端末の制御を握るフォアグラウンドのプロセスグループになるかを制御する。
プロセスグループは常にひとつのリーダーから始まるが、必ずしも常にリーダーが必要というわけではなく、リーダーが他のプロセスより先に終了しても構わない。[1] POSIXの仕様では、プロセスが偶然にグループリーダーなることはないと定めている。そのため、あるプロセスIDがプロセスグループIDとして使われている間は、それがプロセスIDとして再利用されないようにする必要がある。プロセスグループのリーダーになるには、明示的に setpgid()
または setsid()
システムコールを呼び出す必要がある。
setpgid()
システムコールは新たなプロセスグループを生成したり、プロセスを既存のプロセスグループに入れたりする汎用の呼び出しである。リーダーになるには、自身のプロセスIDを指定すればよいが、通常 setpgid(0,0)
という形で呼び出す。シェルがコマンドパイプラインのために新たな子プロセスをfork
すると、親であるシェルプロセスと子プロセスは直ちにそのプロセスをプロセスグループリーダーにしようとする。(両者がそれを試みるのは、子プロセスがプロセスグループリーダーになろうとすること、子プロセスがコマンドを実行しようとすること、親または端末デバイスドライバがジョブコントロールのシグナルをそのプロセスグループに送ろうとすること、これらの競合状態が発生するのを防ぐためである。)
プロセスグループ自体はセッション (session) の一員となる。これはテキストユーザインタフェースが使われているUnix系システムで使われたもので、いわゆる「ログインセッション」を意味している。グラフィカルユーザインタフェース (GUI) が使われるようになってこのコンセプトはほとんど意味がなくなり、カーネルがセッションに関して行っていた処理の大部分も無視されている。GUIではログインセッションに関しては全く別の機構が使用されている。セッションリーダーと呼ばれるひとつのプロセスが制御端末とやり取りして端末が切断されるときにセッション内の全プロセスが停止することを保証する。セッションリーダーがいない場合、その端末のフォアグラウンドのプロセスグループがセッション内の他のプロセスグループの面倒も見ることが期待されている。プロセスは異なるセッションのプロセスグループに移動することはできず、プロセスグループも別のセッションに移動することはできない。プロセスグループを生成するプロセスは、自身が入っているセッション内でしかプロセスグループを生成できない。
setsid()
システムコールを使用して新しいセッションを作る。成功すると、プロセスグループは複数のセッションにまたがることができないため、そのプロセスは同時に新たなプロセスグループリーダーにもなる。つまり、このシステムコールはひとつの新しいプロセスグループを持つ新しいセッションを生成することを目的としている。そのとき現在のプロセスがセッションとプロセスグループのリーダーとなる。注意点として、既存のプロセスおよびプロセスグループがセッションを移動することは仕様上許されていないため、プロセスグループのリーダーであるプロセスが setsid()
を実行することはできず、エラーとなる。[2]