「プロセスの作成 fork」の版間の差分
提供: C言語入門
(ページの作成:「Unixでは、新しいプロセスを作成するためにforkシステムコールを使用します。forkしたプロセスを親プロセス、forkで作成された...」) |
(相違点なし)
|
2014年5月15日 (木) 00:12時点における版
Unixでは、新しいプロセスを作成するためにforkシステムコールを使用します。forkしたプロセスを親プロセス、forkで作成されたプロセスを子プロセスと呼びます。forkによりプロセスは、複製されます。親プロセスがfork前に開いていたファイルは、子プロセスも開いたまま、受け継がれます。
読み方
- fork
- ふぉーく
目次
概要
一般的には、親プロセスは、子プロセスの終了を待ちます。子プロセスが終了したときには、終了ステータスなどの情報をOSが保存しています。親プロセスは、子プロセスの終了処理として、wait系システムコールでOSから終了ステータスを受け取ります。ステータスを受け取るまで、OSが保存し続けるため、waitでステータスを受け取らずにforkを繰り返すと、システムリソースを圧迫してしまいます。
シグナルで子プロセスの終了を知ることもできます。
waitシステムコールでステータスを受け取ったとき、プログラムの終了ステータスやどのように終了したのかを知ることができます。「プログラムの終了ステータス」は、exit()で渡された値です。どのように終了したか、というのは、コアダンプをしたのか、シグナルによって終了させられたのかがわかります。 WEXITSTATUSなどのマクロが用意されています。WIFEXITEDは、正常に終了したかを調べます。WEXITSTATUSは、exit系関数で渡された値を取得します。
forkファミリー
forkには、いくつかのシステムコールが存在します。
- fork
- vfork
- rfork
ヘッダファイル
fork
#include <unistd.h> pid_t fork(void);
wait
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t wpid, int *status, int options); #include <sys/signal.h> int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options); #include <sys/time.h> #include <sys/resource.h> pid_t wait3(int *status, int options, struct rusage *rusage); pid_t wait4(pid_t wpid, int *status, int options, struct rusage *rusage); pid_t wait6(idtype_t idtype, id_t id, int *status, int options, struct __wrusage *wrusage, siginfo_t *infop);
単純なforkの例
この例は、完全なプログラムとはいえません。
ソースコード fork1.c
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> // fork #include <unistd.h> // fork #include <err.h> #include <errno.h> int main(int argc, char *argv[]) { pid_t pid; pid = fork (); if (-1 == pid) { err (EXIT_FAILURE, "can not fork"); } else if (0 == pid) { // child puts ("child"); exit(EXIT_SUCCESS); } else { // parent puts ("parents"); } exit (EXIT_SUCCESS); }
コンパイル
$ cc fork1.c
実行例
$ ./a.out parents child
単純なwaitの例
wait.c
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <sys/types.h> // fork/wait #include <unistd.h> // fork/sleep #include <sys/wait.h> // fork/wait #include <err.h> #include <errno.h> int main(int argc, char *argv[]) { int status = 0; pid_t wait_pid; pid_t pid; pid = fork (); if (-1 == pid) { err (EXIT_FAILURE, "can not fork"); } else if (0 == pid) { // child (void) puts ("child start"); sleep (5); // 子プロセスの長い処理 (void) puts ("child end"); exit (EXIT_SUCCESS); /* NOTREACHED */ } // parent (void) printf ("parents, child is %d\n", pid); wait_pid = wait (& status); if (wait_pid == -1) { // wait が失敗した err (EXIT_FAILURE, "wait error"); } (void) printf ("child = %d, status=%d\n", wait_pid, status); exit (EXIT_SUCCESS); }
コンパイル
$ cc wait.c
実行例
$ ./a.out parents, child is 35975 child start child end child = 35975, status=0
wait系のマクロ
WIFCONTINUED(status) True if the process has not terminated, and has continued after a job control stop. This macro can be true only if the wait call specified the WCONTINUED option). WIFEXITED(status) True if the process terminated normally by a call to _exit(2) or exit(3). WIFSIGNALED(status) True if the process terminated due to receipt of a signal. WIFSTOPPED(status) True if the process has not terminated, but has stopped and can be restarted. This macro can be true only if the wait call spec‐ ified the WUNTRACED option or if the child process is being traced (see ptrace(2)). Depending on the values of those macros, the following macros produce the remaining status information about the child process: WEXITSTATUS(status) If WIFEXITED(status) is true, evaluates to the low‐order 8 bits of the argument passed to _exit(2) or exit(3) by the child. WTERMSIG(status) If WIFSIGNALED(status) is true, evaluates to the number of the signal that caused the termination of the process. WCOREDUMP(status) If WIFSIGNALED(status) is true, evaluates as true if the termina‐ tion of the process was accompanied by the creation of a core file containing an image of the process when the signal was received. WSTOPSIG(status) If WIFSTOPPED(status) is true, evaluates to the number of the signal that caused the process to stop.
関連項目
- プロセスの作成 fork
- 複数の子プロセスをforkする
- コマンドの実行 exec
- popenでコマンドの出力を読み込む