VFORK(2) | Linux Programmer's Manual | VFORK(2) |
名前¶
vfork - 子プロセスを生成し親プロセスを停止させる
書式¶
#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);
glibc
向けの機能検査マクロの要件
(feature_test_macros(7) 参照):
vfork(): _BSD_SOURCE || _XOPEN_SOURCE >= 500
説明¶
規格の説明¶
(POSIX.1 より引用) vfork() 関数は fork(2) と同じ働きをするが、 vfork() で作成されたプロセスが vfork() からの返り値を格納している pid_t 型の変数以外を変更したり、 vfork() を呼び出している関数から return したり、 _exit(2) や exec(3) 族の関数をコールする前に他の関数をコールした場合の動作が 未定義であるという点が異なる。
LINUX での説明¶
vfork() は fork(2) と全く同じように呼び出したプロセスの子プロセスを生成する。 詳しい説明と返り値、エラーについては fork(2) を参照すること。
vfork() は clone(2) の特殊な場合である。 親プロセスのページテーブルのコピーを行わずに新しいプロセスを 作成するために使用する。これは性能に敏感なアプリケーションにおいて 子プロセスを生成してすぐに execve(2) する場合に有用かもしれない。
vfork() は fork(2) と違い、子プロセスが終了するか、 execve(2) をコールするまで親プロセスを停止 (suspend) させる。 子プロセスの終了は、 exit(2) の呼び出しによる通常終了、 致命的なシグナルの配送後の異常終了の二つのケースがある。 この時点までは、子プロセスはスタックを含む全てのメモリを 親プロセスと共有する。 子プロセスは現在の関数から return してはならず、 exit(3) もコールしてはならないが、 _exit(2) ならばコールしてもよい。
シグナルハンドラは継承されるが、共有はされない。 親プロセスへのシグナルは、子プロセスが親プロセスのメモリを 解放した後 (すなわち、子プロセスが終了するか execve(2) を呼んだ後) に到着する。
歴史的な説明¶
Linux において fork(2) は書き込み時コピー (copy-on-write) ページを使用して実装されている。 そのため fork(2) を使用することによって被る損害は親プロセスのページ・テーブルを 複製するために必要な時間とメモリだけである。 しかしながら、忌しき昔には fork(2) は呼び出したプロセスのデータ空間の全てのコピーしていたが、 これはしばしば不必要であった。なぜなら、たいていはすぐ後に exec(3) を実行していたからである。 この場合の効率を上げるために BSD は vfork() システムコールを導入して親プロセスのアドレス空間を完全にコピー するかわりに、 execve(2) をコールするか exit が起きるまで親プロセスのメモリと制御スレッド を借りるようにした。 親プロセスは子プロセスがその資源を使用している間は停止された。 vfork() は使いにくいものであった: 例えば、親プロセスの変数を変更しな いようにするためにはどの変数がレジスタに保持されているかを知らな ければならなかった。
準拠¶
4.3BSD, POSIX.1-2001. POSIX.1-2008 では、 vfork() の規定が削除されている。 vfork() コールは他のオペレーティング・システムの同名のコールと ちょっと似ているかもしれない。規格が vfork() に要求していることは、 fork(2) に要求していることよりは弱い。したがって、 両者を同じものとして実装しても、規格に準拠していることになる。 特にプログラマーは、子プロセスが終了するか execve(2) を呼び出すまで親プロセスが停止していることや、メモリを共有するこ とによる特殊な動作をあてにすべきではない。
注意¶
Linux での注意¶
pthread_atfork(3) を使って設定された fork ハンドラは NPTL スレッドライブラリコールを採用したマルチスレッドプログラムでは 呼び出されない。一方、LinuxThreads スレッドライブラリを使った プログラムでは、fork ハンドラは呼び出される。 (Linux のスレッドライブラリの説明は pthreads(7) を参照。)
歴史¶
vfork() システムコールは 3.0BSD に現われた。 4.4BSD において fork(2) の同義語となったが、NetBSD では再び導入された。 http://www.netbsd.org/Documentation/kernel/vfork.html を参照。 Linux では 2.2.0-pre6 あたりまでは fork(2) と等価であった。(i386 では) 2.2.0-pre9 から (他のアーキテクチャでは 少し遅れて) 独立したシステムコールとなった。 glibc でのサポートは glibc-2.0.112 で追加された。
バグ¶
Linux がこの過去の亡霊を復活させたことは、むしろ不幸と言うべきである。 BSD のマニュアルには、 「このシステムコールは妥当なシステム共有機構が実装された場合には 削除される。ユーザは vfork() のメモリ共有機能に依存するべきではない。何故ならば、このシステムコール が削除された場合には、それは fork(2) の同義語とされるからである。」と書かれている。
シグナルの扱いの詳細は不明瞭でシステムごとに異っている。 BSD のマニュアルには、 「デッドロック状態になる可能性があるので vfork() の途中の子プロセスに SIGTTOU や SIGTTIN シグナルを送信してはならない; さらに出力や ioctl は許されるが、入力を試みた場合には結果はファイル終端 (EOF) になる。」 と書かれている。
関連項目¶
2008-10-30 | Linux |