Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       wait, waitpid, waitid - プロセスの状態変化を待つ

書式

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

       pid_t wait(int *wstatus);

       pid_t waitpid(pid_t pid, int *wstatus, int options);

       int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
                       /* これは glibc と POSIX のインターフェイスである。
                          生のシステムコールについての情報は「注意」の節を参照。 */

   glibc 向けの機能検査マクロの要件 (feature_test_macros(7)  参照):

       waitid():
           glibc 2.26 以降: _XOPEN_SOURCE >= 500 ||
               _POSIX_C_SOURCE >= 200809L
           glibc 2.25 以前:
               _XOPEN_SOURCE
                   || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
                   || /* Glibc versions <= 2.19: */ _BSD_SOURCE

説明

       これらのシステムコールはいずれも、呼び出し元プロセスの子プロセスの  状態変化を待ち、状態が
       変化したその子プロセスの情報を取得するのに 使用される。  状態変化とは以下のいずれかである:
       子プロセスの終了、シグナルによる子プロセスの停止、 シグナルによる子プロセスの再開。 子プロ
       セスが終了した場合は、wait を実行することで、 システムがその子プロセスに関連するリソースを
       解放できるようになる。  wait が実行されなかった場合には、終了した子プロセスは 「ゾンビ」状
       態で残り続ける (下記の注意の章を参照のこと)。

       子プロセスの状態変化がすでに発生していた場合、これらのコールは  すぐに復帰する。それ以外の
       場合は、子プロセスの状態変化が起こるか、  シグナルハンドラーによりシステムコールが中断され
       るまで、 停止 (block) する (後者は、 sigaction(2)  の SA_RESTART  フラグによりシステムコー
       ルが自動的に再スタートするようになっていない  場合の動作である)。 以下の説明では、状態変化
       が起こったがこれらのシステムコールのいずれかに  よって待たれていない子プロセスを  waitable
       (待ち可能) と呼ぶ。

   wait()  waitpid()
       wait()   システムコールは、子プロセスのいずれかが終了するまで 呼び出し元のスレッドの実行を
       一時停止する。 呼び出し wait(&wstatus) は以下と等価である:

           waitpid(-1, &wstatus, 0);

       waitpid() システムコールは、 pid 引数で指定した子プロセスの状態変化が起こるまで、 呼び出し
       元のスレッドの実行を一時停止する。デフォルトでは、  waitpid() は子プロセスの終了だけを待つ
       が、この動作は options 引数により変更可能である。

       pid に指定できる値は以下の通り:

       < -1   プロセスグループID  が  pid  の絶対値に等しい子プロセスのいずれかが終了するまでを待
              つ。

       -1     子プロセスのどれかが終了するまで待つ。

       0      プロセスグループ  ID が、waitpid() が呼ばれた時点での呼び出し元のプロセスのプロセス
              グループ ID と等しい子プロセスを待つ。

       > 0    プロセスID が pid に等しい子プロセスを待つ。

       options の値は次の定数の 0 個以上の論理和である:

       WNOHANG
              状態変化が起こった子プロセスがない場合にすぐに復帰する。

       WUNTRACED
              子プロセスが停止した場合にも復帰する (子プロセスが ptrace(2)   でトレースされている
              場合は除く)。 このオプションが指定されていない場合でも、停止したプロセスが 「トレー
              ス (traced)」されていれば、子プロセスの状態が報告される。

       WCONTINUED (Linux 2.6.10 以降)
              停止した子プロセスが SIGCONT の配送により再開した場合にも復帰する。

       (Linux 専用オプションについては後述する)

       wstatus が NULL でなければ、 wait()  や waitpid()  は status で指す int に状態情報を格納す
       る。  この整数は以下のマクロを使って検査できる。  (これらのマクロの引数には、  wait()   や
       waitpid() が書き込んだ整数そのものを指定する。ポインターではない!)

       WIFEXITED(wstatus)
              子プロセスが正常に終了した場合に真を返す。 「正常に」とは、  exit(3)   か  _exit(2)
              が呼び出された場合、もしくは main() から復帰した場合である。

       WEXITSTATUS(wstatus)
              子プロセスの終了ステータスを返す。 終了ステータスは status 引数の下位 8ビットで構成
              されており、 exit(3)  や  _exit(2)   の呼び出し時に渡された値、もしくは  main()  の
              return  文の 引数として指定された値である。 このマクロを使用するのは WIFEXITED が真
              を返した場合だけにすべきである。

       WIFSIGNALED(wstatus)
              子プロセスがシグナルにより終了した場合に真を返す。

       WTERMSIG(wstatus)
              子プロセス終了の原因となったシグナルの番号を返す。         このマクロを使用するのは
              WIFSIGNALED が真を返した場合だけにすべきである。

       WCOREDUMP(wstatus)
              returns true if the child produced a core dump (see core(5)).  This macro should be
              employed only if WIFSIGNALED returned true.

              This macro is not specified in POSIX.1-2001 and  is  not  available  on  some  UNIX
              implementations  (e.g.,  AIX,  SunOS).   Therefore,  enclose  its use inside #ifdef
              WCOREDUMP ... #endif.

       WIFSTOPPED(wstatus)
              子プロセスがシグナルの配送により停止した場合に真を返す。 これが真になるのは、システ
              ムコールが WUNTRACED を指定して呼び出された場合か、子プロセスがトレースされている場
              合 (ptrace(2)  参照) だけである。

       WSTOPSIG(wstatus)
              子プロセスを停止させたシグナルの番号を返す。 このマクロを使用するのは WIFSTOPPED が
              0 以外を返した場合だけにすべきである。

       WIFCONTINUED(wstatus)
              (Linux 2.6.10 以降)  子プロセスが SIGCONT の配送により再開した場合に真を返す。

   waitid()
       waitid()   システムコール (Linux 2.6.9 以降で利用可能) を使うと、 子プロセスのどの状態変化
       を待つかについてより細かな制御ができる。

       引数 idtypeid でどの子プロセスを待つかを選択する:

       idtype == P_PID
              プロセスID が id と一致する子プロセスを待つ。

       idtype == P_PIDFD (since Linux 5.4)
              Wait for the child referred to by the PID file descriptor specified  in  id.   (See
              pidfd_open(2)  for further information on PID file descriptors.)

       idtype == P_PGID
              Wait  for  any  child whose process group ID matches id.  Since Linux 5.4, if id is
              zero, then wait for any child that is in the same process  group  as  the  caller's
              process group at the time of the call.

       idtype == P_ALL
              子プロセス全部を対象に待つ。 id は無視される。

       子プロセスのどの状態変化を待つかは以下のフラグで指定する (options には 1個以上のフラグの論
       理和をとって指定する):

       WEXITED
              子プロセスの終了を待つ。

       WSTOPPED
              子プロセスがシグナルの配送により停止するのを待つ。

       WCONTINUED
              (停止していた) 子プロセスが SIGCONT が配送されて再開するのを待つ。

       さらに以下のフラグを論理和の形で options に指定できる:

       WNOHANG
              waitpid()  と同様。

       WNOWAIT
              waitable 状態のプロセスをそのままにする。この後で wait コールを  使って、同じ子プロ
              セスの状態情報をもう一度取得することができる。

       成功した場合には、 waitid()  は infop が指す siginfo_t 構造体の以下のフィールドを設定する:

       si_pid 子プロセスのプロセスID。

       si_uid 子プロセスの実ユーザーID (このフィールドは他のほとんどの実装では設定されない)。

       si_signo
              常に SIGCHLD が設定される。

       si_status
              _exit(2)  (か exit(3))  に指定された子プロセスの終了ステータス、もしくは 子プロセス
              の終了、停止、再開の原因となったシグナルが設定される。 このフィールドをどう解釈する
              かは、 si_code フィールドを参照して決めることができる。

       si_code
              以下のいずれかが設定される:   CLD_EXITED   (子プロセスが  _exit(2)   を呼び出した);
              CLD_KILLED (シグナルにより子プロセスが kill された); CLD_DUMPED (シグナルにより子プ
              ロセスが  kill され、コアダンプが行われた); CLD_STOPPED (シグナルにより子プロセスが
              停止した);     CLD_TRAPPED      (トレースされていた子プロセスがトラップを受信した);
              CLD_CONTINUED (SIGCONT により子プロセスが再開された)。

       If  WNOHANG  was specified in options and there were no children in a waitable state, then
       waitid()  returns 0 immediately and the state of the siginfo_t  structure  pointed  to  by
       infop  depends on the implementation.  To (portably) distinguish this case from that where
       a child was in a waitable state, zero out the si_pid field before the call and check for a
       nonzero value in this field after the call returns.

       POSIX.1-2008  Technical  Corrigendum  1  (2013)  adds the requirement that when WNOHANG is
       specified in options and there were no children in a waitable state, then waitid()  should
       zero  out  the  si_pid  and  si_signo  fields  of  the  structure.   On  Linux  and  other
       implementations that adhere to this requirement, it is  not  necessary  to  zero  out  the
       si_pid field before calling waitid().  However, not all implementations follow the POSIX.1
       specification on this point.

返り値

       wait(): 成功すると、終了した子プロセスのプロセスID を返す。 エラーの場合 -1 を返す。

       waitpid(): 成功すると、状態が変化した子プロセスのプロセスID を返す。 WNOHANG  が指定されて
       いて、 pid で指示された子プロセスが一つ以上存在するが、どの子プロセスでも 状態変化が起こっ
       ていなかった場合は、 0 を返す。 エラーの場合 -1 を返す。

       waitid(): 成功すると 0 を返す。 WNOHANG が指定されていて、 pid  で指示された子プロセスで状
       態変化が起こっていなかった場合にも 0 を返す。

       エラーの場合 -1 を返す。 エラーの場合、これらのシステムコールはいずれも errno に適切な値を
       設定する。

エラー

       ECHILD (wait()  の場合)  呼び出し元プロセスには、wait を行っていない子プロセスはない。

       ECHILD (waitpid()  か waitid()  の場合)  pid (waitpid())  か idtypeid (waitid())  で指
              定したプロセスが存在しないか、呼び出し元プロセスの子プロセスでない  (SIGCHLD の動作
              に SIG_IGN を設定した場合には、自分自身の子プロセスでも起こりうる。  スレッドに関し
              ては「Linux での注意」の節も参照すること)。

       EINTR  WNOHANG  が設定されておらず、禁止  (block)  されていないシグナルや SIGCHLD を受信し
              た。 signal(7) 参照。

       EINVAL options 引数が不正である。

準拠

       SVr4, 4.3BSD, POSIX.1-2001.

注意

       A child that terminates, but has not been waited  for  becomes  a  "zombie".   The  kernel
       maintains  a minimal set of information about the zombie process (PID, termination status,
       resource usage information)  in order to allow the parent  to  later  perform  a  wait  to
       obtain  information  about  the child.  As long as a zombie is not removed from the system
       via a wait, it will consume a slot in the kernel process table, and if this  table  fills,
       it will not be possible to create further processes.  If a parent process terminates, then
       its "zombie" children (if any)  are adopted by init(1), (or  by  the  nearest  "subreaper"
       process  as  defined  through  the  use of the prctl(2) PR_SET_CHILD_SUBREAPER operation);
       init(1)  automatically performs a wait to remove the zombies.

       POSIX.1-2001 では以下のように規定されている。 SIGCHLD  の動作が  SIG_IGN  に設定されたか、
       SIGCHLD  に対して SA_NOCLDWAIT フラグが設定された場合 (sigaction(2)  参照)、終了した子プロ
       セスはゾンビにはならず、 wait()  や waitpid()   の呼び出しは全ての子プロセスが終了するまで
       停止し、 子プロセスが全部終了した後 errnoECHILD を設定して失敗する。 (もともとの POSIX
       標準は SIGCHLDSIG_IGN を設定した場合の振る舞いを未規定のままにしている。 SIGCHLD  のデ
       フォルトの動作が「無視」であるにもかかわらず、 SIGCHLD の動作として SIG_IGN を明示的に設定
       した場合にはゾンビプロセスの子プロセスの扱いが 異なる点に注意すること。)

       Linux 2.6 はこの仕様に準拠している。 しかし、Linux 2.4 (とそれ以前のバージョン) はそうでは
       ない: SIGCHLD が無視される状態で wait()  または waitpid()  が呼び出された場合、 SIGCHLD が
       無視されていないかのように振る舞う。    つまり、呼び出しによって次の子プロセスの終了までブ
       ロックされ、 終了した子プロセスの PID と状態が返される。

   Linux での注意
       Linux  カーネルでは、カーネルによってスケジュールされるスレッドは プロセスと明確に区別でき
       る構成要素ではない。スレッドは Linux 固有の clone(2)  システムコールを使用して生成されるプ
       ロセスに過ぎない。  移植性のある  pthread_create(3)  コールのような他のルーチンは clone(2)
       を使用して実装されている; これらでは waitid()  を使うことはできない。 Linux  2.4  より前で
       は、スレッドは単に特殊なプロセスであったので、 例え同じスレッドグループであっても、 あるス
       レッドが別のスレッドの子プロセスが終了するのを待つことは出来なかった。 しかし、POSIX  では
       このような機能を規定しており、  Linux 2.4 以降では、あるスレッドが同じスレッドグループの他
       のスレッドの  子プロセスが終了するのを待つことができるようになった。  そして将来はこれがデ
       フォルトの動作になるであろう。

       The  following  Linux-specific  options  are for use with children created using clone(2);
       they can also, since Linux 4.7, be used with waitid():

       __WCLONE
              "clone" な子プロセスだけを待つ。 指定されなかった場合は非 "clone"  な子プロセスだけ
              を待つ    ("clone"   な子プロセスは、終了時に親プロセスへ全くシグナルを送らないか、
              SIGCHLD 以外のシグナルを送る)。 このオプションは __WALL  も指定された場合は無視され
              る。

       __WALL (Linux 2.4 以降)
              "clone" であるかないかに関わらず、 全ての子プロセスを待つ。

       __WNOTHREAD (Linux 2.4 以降)
              同じスレッドグループの他のスレッドの子プロセスは待たない。  Linux  2.4 より前ではデ
              フォルトであった。

       Since Linux 4.7, the __WALL flag is automatically implied if the child is being ptraced.

   C ライブラリとカーネルの違い
       wait()  is actually a library function that  (in  glibc)  is  implemented  as  a  call  to
       wait4(2).

       On  some  architectures,  there  is  no waitpid()  system call; instead, this interface is
       implemented via a C library wrapper function that calls wait4(2).

       生の waitid() システムコールは struct rusage * 型の第 5 引数を取る。 この引数が NULL  以外
       の場合、 この引数が子プロセスのリソース使用状況を返すのに使用される。 これは wait4(2) と同
       じ方法である。 詳細は getrusage(2) を参照。

バグ

       POSIX.1-2008 によると、 waitid() を呼び出すアプリケーションは、 infopsiginfo_t  構造体
       を指していること  (つまり infop が NULL でないポインターであること) を保証しなければならな
       い。 Linux では、 infop が NULL の場合、 waitid() は成功し、wait  している子プロセスのプロ
       セス  ID を返す。 アプリケーションは、この食い違った、非標準で、不必要な機能に依存しないよ
       うにすべきである。

       以下のプログラムは、 fork(2)  と waitpid()  の使用方法の例を示している。  このプログラムで
       は子プロセスを生成する。     コマンドライン引数が指定されなかったときは、     子プロセスは
       pause(2)  を使ってその実行を一時停止し、ユーザーがその子プロセスに  シグナルを送信できるよ
       うにする。  コマンドライン引数が指定された場合は、 子プロセスは直ちに終了し、 コマンドライ
       ンで指定された整数を終了ステータスとして使用する。 親プロセスは、 waitpid()   を使って子プ
       ロセスを監視し、  wait のステータス値を上記の W*() マクロを使って解析するという ループを実
       行する。

       以下のシェルのセッションはこのプログラムの使用例を示したものである。

           $ ./a.out &
           Child PID is 32360
           [1] 32359
           $ kill -STOP 32360
           stopped by signal 19
           $ kill -CONT 32360
           continued
           $ kill -TERM 32360
           killed by signal 15
           [1]+  Done                    ./a.out
           $

   プログラムのソース

       #include <sys/wait.h>
       #include <stdint.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <stdio.h>

       int
       main(int argc, char *argv[])
       {
           pid_t cpid, w;
           int wstatus;

           cpid = fork();
           if (cpid == -1) {
               perror("fork");
               exit(EXIT_FAILURE);
           }

           if (cpid == 0) {            /* Code executed by child */
               printf("Child PID is %jd\n", (intmax_t) getpid());
               if (argc == 1)
                   pause();                    /* Wait for signals */
               _exit(atoi(argv[1]));

           } else {                    /* Code executed by parent */
               do {
                   w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);
                   if (w == -1) {
                       perror("waitpid");
                       exit(EXIT_FAILURE);
                   }

                   if (WIFEXITED(wstatus)) {
                       printf("exited, status=%d\n", WEXITSTATUS(wstatus));
                   } else if (WIFSIGNALED(wstatus)) {
                       printf("killed by signal %d\n", WTERMSIG(wstatus));
                   } else if (WIFSTOPPED(wstatus)) {
                       printf("stopped by signal %d\n", WSTOPSIG(wstatus));
                   } else if (WIFCONTINUED(wstatus)) {
                       printf("continued\n");
                   }
               } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
               exit(EXIT_SUCCESS);
           }
       }

関連項目

       _exit(2),  clone(2),  fork(2),  kill(2),  ptrace(2),  sigaction(2),  signal(2),  wait4(2),
       pthread_create(3), core(5), credentials(7), signal(7)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。