プロセスグループ
プログラム中で新しいプロセス(子プロセス)を生成して処理を行う際、メインプロセスから子プロセスを終了させるのは kill() で簡単にできます。
しかし、子プロセスが更に孫プロセスを生成した場合、孫プロセスをメインプロセスから kill() で終了させることはできません。孫プロセスの PID(プロセス ID)がわからないためです。
スレッドと異なり、プロセスのメモリ空間はそれぞれ独立しているため、直接データのやり取りはできません。
次のプログラムを動かしてみます。ファイル名を a.c とします。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
void start_grandchild() {
int pid;
pid = fork();
if( pid == -1 ) {
printf("fork faild.\n");
}
if( pid == 0 ) {
while( 1 ) {
printf("Grandchild running(pid:%d).\n", getpid());
sleep(3);
}
}
}
pid_t start_child() {
int pid;
pid = fork();
if( pid == -1 ) {
printf("fork faild.\n");
return 0;
}
if( pid == 0 ) {
printf("start grandchild.\n");
start_grandchild();
while( 1 ) {
printf("Child running(pid:%d).\n", getpid());
sleep(2);
}
}
return pid;
}
int main(int argc, char *argv) {
pid_t pid;
printf("start child.\n");
pid = start_child();
sleep(10);
printf("Stop child process.\n");
kill(pid, SIGTERM);
sleep(10);
return 0;
}
コンパイルして実行してみます。
$ gcc a.c
$ ./a.out
start child.
start grandchild.
Child running(pid:2615).
Grandchild running(pid:2616).
Child running(pid:2615).
Grandchild running(pid:2616).
Child running(pid:2615).
Child running(pid:2615).
Grandchild running(pid:2616).
Child running(pid:2615).
Grandchild running(pid:2616).
Stop child process.
Grandchild running(pid:2616).
Grandchild running(pid:2616).
Grandchild running(pid:2616).
$ Grandchild running(pid:2616).
Grandchild running(pid:2616).
Grandchild running(pid:2616).
Grandchild running(pid:2616).
kill 2616
$
最後は kill コマンドで孫プロセスを終了させています。
このような場合、子プロセスで新たに PGID(プロセスグループ ID)を設定することでそのプロセスグループに対して signal を送ることができます。
setpgid() で子プロセスのプロセスグループ ID を変更し、kill() の代わりに killpg() を使って終了させます。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
void start_grandchild() {
int pid;
pid = fork();
if( pid == -1 ) {
printf("fork faild\n");
}
if( pid == 0 ) {
while( 1 ) {
printf("Grandchild running(pid:%d).\n", getpid());
sleep(3);
}
}
}
pid_t start_child() {
int pid;
pid = fork();
if( pid == -1 ) {
printf("fork faild\n");
return 0;
}
if( pid == 0 ) {
pid = getpid();
printf("set pgid %d.\n", pid);
setpgid(pid, pid);
printf("start grandchild.\n");
start_grandchild();
while( 1 ) {
printf("Child running(pid:%d).\n", getpid());
sleep(2);
}
}
return pid;
}
int main(int argc, char *argv) {
pid_t pid;
printf("start child.\n");
pid = start_child();
sleep(10);
printf("Stop child process.\n");
killpg(pid, SIGTERM);
sleep(10);
return 0;
}
実行してみます。
$ gcc a.c
$ ./a.out
start child.
set pgid 2696.
start grandchild.
Child running(pid:2696).
Grandchild running(pid:2697).
Child running(pid:2696).
Grandchild running(pid:2697).
Child running(pid:2696).
Child running(pid:2696).
Grandchild running(pid:2697).
Child running(pid:2696).
Grandchild running(pid:2697).
Stop child process.
$
子プロセスも孫プロセスも終了します。子プロセスでシグナルハンドラを使い、孫プロセスを終了させる方法もあると思いますが、プロセスグループを使ったほうがスッキリすると思います。
ディスカッション
コメント一覧
まだ、コメントがありません