「プロセスの作成 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.

関連項目