「複数の子プロセスをforkする」の版間の差分
提供: C言語入門
(ページの作成:「fork()を何度も呼び出すことで、複数の子プロセスを作成できます。一定数の複数の子プロセスをfork()し、waitpid()で回収しつつ...」) |
(相違点なし)
|
2014年5月17日 (土) 00:08時点における版
fork()を何度も呼び出すことで、複数の子プロセスを作成できます。一定数の複数の子プロセスをfork()し、waitpid()で回収しつつ、一定数の子プロセスを維持する例です。
概要
ここで紹介するのは、複数の子プロセスを持ち、子プロセスに処理を任せるようなマルチプロセスのデーモンを作成するときに参考にするための簡単な例です。 Apache (preforkモデル)のようなマルチプロセスのデーモンは、子プロセスを生成し、子プロセスに処理を任せます。そのようなアプリケーションは、子プロセスが終了したら、新たに作成します。
multi_fork.c の例
このプログラムは、以下のポリシーで作成されています。
- 子プロセスはランダムの秒数だけ実行され、終了します。
- 同時に持つ子プロセスの数の上限を持ちます。
- 子プロセスの数の上限までfork()したら、子供が終了するのを待ちます。
- fork()する最大数を設定しています。最大数に達したら、子プロセスのすべての終了を待ち、プログラムも終了します。
ソースコード multi_fork.c
/* * multi_fork.c * Copyright (C) 2014 kaoru <kaoru@bsd> */ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> // fork #include <unistd.h> // fork #include <sys/wait.h> // wait #include <err.h> #include <errno.h> pid_t Fork() { pid_t pid = fork(); if (-1 == pid) { err(EXIT_FAILURE, "can not fork"); } return pid; } pid_t Waitpid(pid_t wpid, int *status, int options) { for(;;){ pid_t pid = waitpid(wpid, status, options); if (-1 == pid){ if (EINTR == errno){ (void) printf ("EINTR\n"); continue; } if (ECHILD == errno){ (void) printf("no child\n"); } else { err(EXIT_FAILURE, "can not wait"); } } return (pid); } } void wait_children (ssize_t *child) { int status; int options = WEXITED; bool is_first = true; for(;*child > 0;) { pid_t pid = Waitpid(-1, &status, options); if (-1 == pid) { return; } else if (0 == pid) { return; } (*child)--; if (is_first) { is_first = false; options = WNOHANG; } } } void doit() { srandom( getpid() ); unsigned int sleep_sec = random() % 3; sleep (sleep_sec); } int main(int argc, char *argv[]) { const ssize_t child_max = 30; // 同時最大子プロセス数 const ssize_t fork_max = 70; // forkの最大数 ssize_t child = 0; // 現在の子プロセスの数 ssize_t fork_count = 0; // 現在のfork()の回数 ssize_t i = 0; for ( ; fork_count <= fork_max; ) { (void) printf ("fork_count=%lu, child=%lu\n", fork_count, child); for (; child < child_max; child++, fork_count++) { pid_t pid = Fork (); if (0 == pid) { doit(); _exit(EXIT_SUCCESS); } } wait_children(&child); } while (child > 0) { wait_children(&child); } exit (EXIT_SUCCESS); }
コンパイル
cc --out multi_fork.c -o multi_fork
実行例
% ./multi_fork fork_count=0, child=0 fork_count=30, child=18 fork_count=42, child=27 fork_count=45, child=29 fork_count=46, child=29 fork_count=47, child=29 fork_count=48, child=29 fork_count=49, child=29 fork_count=50, child=29 fork_count=51, child=10
関連項目
- プロセスの作成 fork
- 複数の子プロセスをforkする
- コマンドの実行 exec
- popenでコマンドの出力を読み込む