fork
fork(フォーク)は、UNIX系システムコールのひとつで、プロセスのコピーを生成するものである。新たに作り出されたプロセスを子プロセス、fork()を呼び出したプロセスを親プロセスと呼ぶ。また、マルチスレッド環境でスレッドのコピーを作ることもforkと呼ぶことがある。
UNIX系オペレーティングシステムでは、fork()システムコールの戻り値によって親と子の処理を区別する。子プロセスではfork()の戻り値は0であり、親プロセスの戻り値は新たに生成された子プロセスのプロセス識別子、エラーが起きた場合は-1である。
forkが呼び出されると、子プロセスのためのアドレス空間が新たに作成される。子プロセスのアドレス空間には親プロセスが持っていた全セグメントのコピーがあるが、コピーオンライト機能によって実際の物理メモリの確保は遅延される。親プロセスと子プロセスは独立して実行される。
目次 |
[編集] 例
以下はC言語でのfork使用例(コードの断片)である。コード内の「子プロセス」の部分と「親プロセス」の部分は並行して実行される。
pid_t pid;
pid = fork();
if (pid == 0) {
/* 子プロセス:
* fork()が0を返す場合、子プロセスである
* 1秒に1ずつ、10まで数える。
*/
int j;
for (j=0; j < 10; j++) {
printf("child: %d\n", j);
sleep(1);
}
_exit(0); /* exit() を使わない点に注意 */
} else if(pid > 0) {
/* 親プロセス:
* 0以外の場合、親プロセスである
* ここでも10まで数える
*/
int i;
for (i=0; i < 10; i++) {
printf("parent: %d\n", i);
sleep(1);
}
} else {
/* エラー処理 */
fprintf(stderr, "couldn't fork");
exit(1);
}
このコードは以下のような表示をする。
parent: 0 child: 0 child: 1 parent: 1 parent: 2 child: 2 child: 3 parent: 3 parent: 4 child: 4 child: 5 parent: 5 parent: 6 child: 6 child: 7 parent: 7 parent: 8 child: 8 child: 9 parent: 9
出力の順序はカーネルが決定する。
[編集] Fork-Exec
Fork-Execは、UNIXで一般的に使われる手法であり、新たなプログラムをプロセスとして実行する。fork()は親プロセスを2つの同一内容のプロセスに(フォークの先のように)分岐させるシステムコールである。fork()によって子プロセスが親プロセスのコピーとして生成され、子プロセスがexec()システムコールを呼び出すことで(子プロセス)自身の内容を置き換える。
子プロセスがexec()を呼び出すと、そのアドレス空間の内容は全て失われ、指定されたプログラムを実行するためのアドレス空間のマッピングが新しく設定される。これをオーバーレイと呼ぶ。アドレス空間は全て置き換えられるが、オープン済みファイルのファイル記述子群は close-on-exec が指定されたときだけ exec()時に自動的にクローズされる。この特徴を利用して、fork()を呼び出す前にパイプを作成しておき、exec()で指定された新しいプログラムとの通信を行うというUNIX特有の手法が実現されている。
このことは、fork()されてからexec()されるまでの間、同一名称のプロセスが2つ見えてしまうことがあることを意味しており、注意が必要である。 (システム管理ソフトなどでプロセス監視をしている場合など)
なお、Microsoft WindowsではCreateProcess()で Fork-Exec を実現している。
[編集] 関連項目
[編集] 外部リンク
- Manpage of FORK Linux JM プロジェクト
- Fork and Exec ケンブリッジ大学 Computing Help(英語)
- Unix Programming Frequently Asked Questions 日本語訳 1.1.3 forkによる子プロセスを終了するときにexitよりも_exitを使うのはなぜですか?