other versions
other sections
WAIT(2) | Linux Programmer's Manual | WAIT(2) |
名前¶
wait, waitpid, waitid - プロセスの状態変化を待つ書式¶
#include <sys/types.h>glibc 向けの機能検査マクロの要件 ( feature_test_macros(7) 参照):
_SVID_SOURCE ||
_XOPEN_SOURCE >= 500 ||
_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* glibc 2.12 以降: */
_POSIX_C_SOURCE >= 200809L
説明¶
これらのシステムコールはいずれも、呼び出し元プロセスの子プロセスの 状態変化を待ち、状態が変化したその子プロセスの情報を取得するのに 使用される。 状態変化とは以下のいずれかである: 子プロセスの終了、シグナルによる子プロセスの停止、 シグナルによる子プロセスの再開。 子プロセスが終了した場合は、wait を実行することで、 システムがその子プロセスに関連するリソースを解放できるようになる。 wait が実行されなかった場合には、終了した子プロセスは 「ゾンビ」状態で残り続ける (下記の注意の章を参照のこと)。wait() と waitpid()¶
wait() システムコールは、子プロセスのいずれかが終了するまで 呼び出し元のプロセスの実行を一時停止する。 呼び出し wait(&status) は以下と等価である:waitpid(-1, &status, 0);
- < -1
- プロセスグループID が pid の絶対値に等しい子プロセスのいずれかが終了するまでを待つ。
- -1
- 子プロセスのどれかが終了するまで待つ。
- 0
- プロセスグループID が呼び出したプロセスのものと等しい 子プロセスを待つ。
- > 0
- プロセスID が pid に等しい子プロセスを待つ。
- WNOHANG
- 状態変化が起こった子プロセスがない場合にすぐに復帰する。
- WUNTRACED
- 子プロセスが停止した場合にも復帰する (子プロセスが ptrace(2) でトレースされている場合は除く)。 このオプションが指定されていない場合でも、停止したプロセスが 「トレース (traced)」されていれば、子プロセスの状態が報告される。
- WCONTINUED (Linux 2.6.10 以降)
- 停止した子プロセスが SIGCONT の配送により再開した場合にも復帰する。
- WIFEXITED(status)
- 子プロセスが正常に終了した場合に真を返す。 「正常に」とは、 exit(3) か _exit(2) が呼び出された場合、もしくは main() から復帰した場合である。
- WEXITSTATUS(status)
- 子プロセスの終了ステータスを返す。 終了ステータスは status 引き数の下位 8ビットで構成されており、 exit(3) や _exit(2) の呼び出し時に渡された値、もしくは main() の return 文の 引き数として指定された値である。 このマクロを使用するのは WIFEXITED が真を返した場合だけにすべきである。
- WIFSIGNALED(status)
- 子プロセスがシグナルにより終了した場合に真を返す。
- WTERMSIG(status)
- 子プロセス終了の原因となったシグナルの番号を返す。 このマクロを使用するのは WIFSIGNALED が真を返した場合だけにすべきである。
- WCOREDUMP(status)
- 子プロセスがコアダンプを生成した場合に真を返す。 このマクロを使用するのは WIFSIGNALED が真を返した場合だけにすべきである。 このマクロは POSIX.1-2001 では規定されておらず、 (AIX, SunOS などの) いくつかの UNIX の実装では利用できない。 必ず #ifdef WCOREDUMP ... #endif で括って使用すること。
- WIFSTOPPED(status)
- 子プロセスがシグナルの配送により停止した場合に真を返す。 これが真になるのは、システムコールが WUNTRACED を指定して呼び出された場合か、子プロセスがトレースされている場合 ( ptrace(2) 参照) だけである。
- WSTOPSIG(status)
- 子プロセスを停止させたシグナルの番号を返す。 このマクロを使用するのは WIFSTOPPED が 0 以外を返した場合だけにすべきである。
- WIFCONTINUED(status)
- (Linux 2.6.10 以降) 子プロセスが SIGCONT の配送により再開した場合に真を返す。
waitid()¶
waitid() システムコール (Linux 2.6.9 以降で利用可能) を使うと、 子プロセスのどの状態変化を待つかについてより細かな制御ができる。- idtype == P_PID
- プロセスID が id と一致する子プロセスを待つ。
- idtype == P_PGID
- プロセスグループID が id と一致する子プロセスを待つ。
- idtype == P_ALL
- 子プロセス全部を対象に待つ。 id は無視される。
- WEXITED
- 子プロセスの終了を待つ。
- WSTOPPED
- 子プロセスがシグナルの配送により停止するのを待つ。
- WCONTINUED
- (停止していた) 子プロセスが SIGCONT が配送されて再開するのを待つ。
- WNOHANG
- waitpid() と同様。
- WNOWAIT
- waitable 状態のプロセスをそのままにする。この後で wait コールを 使って、同じ子プロセスの状態情報をもう一度取得することができる。
- 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 により子プロセスが再開された)。
返り値¶
wait(): 成功すると、終了した子プロセスのプロセスID を返す。 エラーの場合 -1 を返す。エラー¶
- ECHILD
- (wait() の場合) 呼び出し元プロセスには、wait を行っていない子プロセスはない。
- ECHILD
- (waitpid() か waitid() の場合) pid (waitpid()) か idtype と id (waitid()) で指定したプロセスが存在しないか、呼び出し元プロセスの子プロセスでない ( SIGCHLD の動作に SIG_IGN を設定した場合には、自分自身の子プロセスでも起こりうる。 スレッドに関しては「Linux での注意」の節も参照すること)。
- EINTR
- WNOHANG が設定されておらず、禁止 (block) されていないシグナルや SIGCHLD を受信した。 signal(7) 参照。
- EINVAL
- options 引き数が不正である。
準拠¶
SVr4, 4.3BSD, POSIX.1-2001.注意¶
終了したが、wait されていない子プロセスは「ゾンビ」になる。 後で親プロセスが wait を実行して子プロセスについての情報を取得できるように、 カーネルはゾンビプロセスについて最小限の情報 (PID、終了ステータス、 リソース使用状況) を保持する。 ゾンビプロセスは、 wait によってシステムから削除されない限り、 カーネルのプロセステーブルの 1 エントリを消費する。このプロセステーブルが 一杯になると、新たにプロセスを作ることができなくなる。 親プロセスが終了すると、その親プロセスの「ゾンビ」の 子プロセスは (もしあれば) init(8) の養子となる。 init(8) は wait を自動的に実行し、ゾンビを削除する。Linux での注意¶
Linux カーネルでは、カーネルによってスケジュールされるスレッドは プロセスと明確に区別できる構成要素ではない。スレッドは Linux 固有の clone(2) システムコールを使用して生成されるプロセスに過ぎない。 移植性のある pthread_create(3) コールのような他のルーチンは clone(2) を使用して実装されている; これらでは waitid() を使うことはできない。 Linux 2.4 より前では、スレッドは単に特殊なプロセスであったので、 例え同じスレッドグループであっても、 あるスレッドが別のスレッドの子プロセスが終了するのを待つことは出来なかった。 しかし、POSIX ではこのような機能を規定しており、 Linux 2.4 以降では、あるスレッドが同じスレッドグループの他のスレッドの 子プロセスが終了するのを待つことができるようになった。 そして将来はこれがデフォルトの動作になるであろう。 clone(2) を用いて作られた子プロセスには、以下の Linux 固有の options が使用できる。- __WCLONE
- "clone" な子プロセスだけを待つ。 指定されなかった場合は非 "clone" な子プロセスだけを待つ ("clone" な子プロセスは、終了時に親プロセスへ全くシグナルを送らないか、 SIGCHLD 以外のシグナルを送る)。 このオプションは __WALL も指定された場合は無視される。
- __WALL (Linux 2.4 以降)
- "clone" であるかないかに関わらず、 全ての子プロセスを待つ。
- __WNOTHREAD (Linux 2.4 以降)
- 同じスレッドグループの他のスレッドの子プロセスは待たない。 Linux 2.4 より前ではデフォルトであった。
例¶
以下のプログラムは、 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 <stdlib.h> #include <unistd.h> #include <stdio.h> int main(int argc, char *argv[]) { pid_t cpid, w; int status; cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { /* Code executed by child */ printf("Child PID is %ld\n", (long) getpid()); if (argc == 1) pause(); /* Wait for signals */ _exit(atoi(argv[1])); } else { /* Code executed by parent */ do { w = waitpid(cpid, &status, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(status)) { printf("exited, status=%d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("killed by signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("stopped by signal %d\n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("continued\n"); } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); exit(EXIT_SUCCESS); } }
関連項目¶
_exit(2), clone(2), fork(2), kill(2), ptrace(2), sigaction(2), signal(2), wait4(2), pthread_create(3), credentials(7), signal(7)この文書について¶
この man ページは Linux man-pages プロジェクトのリリース 3.41 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2010-09-26 | Linux |