今回は、システムコールfork
やwait
などについて書いていこうと思います。 fork
を呼び出すことで、 子プロセスの生成が出来ます。 また、wait
を呼び出すことで、 親プロセスが子プロセスの終了を待ちます。 以下にプログラム例を示します。
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
pid_t pid;
if((pid = fork()) == 0) {
puts("child process");
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
puts("exit child process");
return 0;
} else {
puts("parent process");
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
wait(NULL);
puts("exit parent process");
}
return 0;
}
fork
, getpid
, getppid
を利用するにはunistd.h
を、wait
を利用するためにはsys/wait.h
をインクルードする必要があります。 fork
は成功時に子プロセスには0を、 親プロセスには子プロセスのPIDを返し、失敗時は-1を返します。 getpid
及びgetppid
はそれぞれ呼び出し元のプロセスと親プロセスのPID(プロセスID)を返します。 getpid
及びgetppid
は常に成功します。 wait
は成功時、終了した子プロセスのPIDを、失敗時に-1を返します。
fork
, getpid
, getppid
, wait
のインタフェースは以下の通り。
fork
pid_t fork(void);
getpid
pid_t getpid(void);
getppid
pid_t getppid(void);
wait
pid_t wait(int *stat_loc);
fork
, getpid
及びgetppid
は引数を取りません。 wait
の第1引数stat_loc
には、 子プロセスの終了ステータスが格納されます。 (第1引数stat_loc
はint
へのポインタ) 上記のプログラム例では、子プロセスの終了ステータスは不要なので、 NULL
ポインタが指定されています。
上のプログラム例では、fork
の呼び出しで子プロセスを生成し、 それぞれ子プロセスと親プロセスで自身のPIDと親プロセスのPIDを表示します。 fork
で子プロセスが生成されると、親プロセスと子プロセスの処理がそれぞれ並行で実行されます。 親プロセスは子プロセスの処理の完了をwait
で待ち、 子プロセスが終了したらwait
の後の処理を実行します。 以下に実行例を示します。
fork
とします。$ ./fork parent process pid: 1601 ppid: 465 child process pid: 1602 ppid: 1601 exit child process exit parent process $
なお、fork
は、扱い方によってはゾンビプロセスを生成する場合がありますので、応用する場合には注意が必要です。
fork
で生成した子プロセスをwait
で待たずに生成してしまうような処理を含んでしまった場合)今回は、並行処理を行うためのシステムコールfork
と、 それに関するシステムコールをいくつか紹介しました。 詳しくはman 2 fork
, man 2 wait
, man 2 getpid
, man 2 getppid
とターミナルに入力し、マニュアルを呼び出してみてください。 次回はpipe
について書こうと考えています。 そんなわけで、今回はここまで。