C言語入門講座。関数、サンプル集を参考にして、 C言語をマスターしよう。初心者から上級者まで。

子プロセスの状態変化を待つ

2012.08.11

wait関数は、呼び出し元プロセスの子プロセスの状態変化を待ちます。子プロセスの状態変化がすでに発生していた場合は、wait関数はすぐに復帰します。それ以外の場合は、子プロセスの状態変化が起こるか、シグナルハンドラによりシステムコールが中断されるまで呼び出し元プロセスは停止します。

なお、ここでの状態変化には、次のような事があります。

  1. 子プロセスの終了。
  2. シグナルによる子プロセスの停止。
  3. シグナルによる子プロセスの再開。

この関数は、C言語のライブラリ関数(標準関数)ではありませんので、コンパイラにより、使えない場合があります。

#include <sys/wait.h>
pid_t wait(int *status);

*statusは子プロセスからの終了ステータスを格納する変数を指定します。なお、終了ステータスが不要な場合は、NULLを指定できます。

戻り値として、処理が成功した場合は、子プロセスのプロセスIDが、失敗した場合は-1を返します。

終了ステータスはexit関数の引数で指定した値そのままではなく、「指定した値 & 0377」です。また、終了ステータスをチェックするための、次のようなマクロがあります。

マクロ 内容
WIFEXITED(status) 子プロセスが正常に終了した場合に真を返します。「正常」とは、exit関数の呼び出しや、main関数から復帰した場合です。
WEXITSTATUS(status) 子プロセスの終了ステータスを返します。終了ステータスはexit関数やmain関数の引数で指定した値です。なお、このマクロはWIFEXITEDマクロが真を返した場合だけ使用したほうがよいでしょう。
WIFSIGNALED(status) 子プロセスがシグナルにより終了した場合に真を返します。
WTERMSIG(status) 子プロセス終了の原因となったシグナルの番号を返します。このマクロはWIFSIGNALEDマクロが真を返した場合だけ使用したほうがよいでしょう。

プログラム 例

#include <stdio.h>
#include <sys/wait.h>

int main()
{
  int         p_id;
  int         status;
  int         return_code = 0;

  if ((p_id = fork()) == 0) {
    /* 子プロセス */
    printf("子プロセス開始\n");

    sleep(10);

    printf("子プロセス終了\n");
  }
  else {
    /* 親プロセス */
    if (p_id != -1) {
      /* 子プロセスの状態変化を待つ */
      wait(&status);

     /* 終了ステータスのチェック */
     if (WIFEXITED(status)) {
        printf("親プロセス : 子プロセスは終了ステータス%dで正常終了しました\n",
               WEXITSTATUS(status));
      }
      if (WIFSIGNALED(status)) {
        printf("親プロセス : 子プロセスはシグナル番号%dで終了しました\n",
               WTERMSIG(status));
      }

      printf("親プロセス終了\n");
    }
    else {
      perror("親プロセス ");
      return_code = 1;
    }
  }

  return return_code;
}

 

例の実行結果

2回目と3回目はバックグラウンドで実行して、psコマンドで子プロセスのプロセスIDを調べた後、killコマンドでシグナルを送っています。(その結果、子プロセスは終了します。)

$ ./wait.exe
子プロセス開始
子プロセス終了
親プロセス : 子プロセスは終了ステータス0で正常終了しました
親プロセス終了
$
$ ./wait.exe &
子プロセス開始
[1] 2731
$ ps
  PID TTY          TIME CMD
 2293 pts/1    00:00:00 bash
 2731 pts/1    00:00:00 wait.exe
 2732 pts/1    00:00:00 wait.exe
 2733 pts/1    00:00:00 ps
$ kill 2732
親プロセス : 子プロセスはシグナル番号15で終了しました
親プロセス終了
$
$ ./wait.exe &
子プロセス開始
[1] 2741
$ ps
  PID TTY          TIME CMD
 2293 pts/1    00:00:00 bash
 2741 pts/1    00:00:00 wait.exe
 2742 pts/1    00:00:00 wait.exe
 2743 pts/1    00:00:00 ps
$ kill -s SIGQUIT 2742
親プロセス : 子プロセスはシグナル番号3で終了しました
親プロセス終了
$

関連記事