Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       vfork - 子プロセスを生成し親プロセスを停止させる

書式

       #include <sys/types.h>
       #include <unistd.h>

       pid_t vfork(void);

   glibc 向けの機能検査マクロの要件 (feature_test_macros(7)  参照):

       vfork():
           glibc 2.12 以降:
               (_XOPEN_SOURCE >= 500) && ! (_POSIX_C_SOURCE >= 200809L)
                   || /* glibc 2.19 以降: */ _DEFAULT_SOURCE
                   || /* glibc 2.19 以前: */ _BSD_SOURCE
           glibc 2.12 より前:
                _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()   differs  from  fork(2)   in that the calling thread is suspended until the child
       terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal
       signal),  or  it makes a call to execve(2).  Until that point, the child shares all memory
       with its parent, including the stack.  The child must not return from the current function
       or  call exit(3)  (which would have the effect of calling exit handlers established by the
       parent process and flushing the parent's stdio(3)  buffers), but may call _exit(2).

       fork(2) と同様に、 vfork() で作成された子プロセスは、  (ファイルディスクリプター、シグナル
       配送定義、カレントワーキングディレクトリなどの)   呼び出し元のプロセスの各種の属性を継承す
       る。 vfork() では、上で説明した仮想アドレス空間の扱いだけが異なる。

       親プロセスへ送られたシグナルは、子プロセスが親プロセスのメモリーを解放した後 (すなわち、子
       プロセスが終了するか 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)   を呼び出すまで親プロセスが停止していることや、メモ
       リーを共有するこ とによる特殊な動作をあてにすべきではない。

注意

       vfork()  の動作は構造的な欠陥と考える人もいるだろうし、 BSD のマニュアルには、「このシステ
       ムコールは妥当なシステム共有機構が実装さ れた場合には削除される。ユーザーは vfork() のメモ
       リー共有機能に依存するべき   ではない。何故ならば、このシステムコール   が削除された場合に
       は、それは fork(2) の同義語とされるからである。」と書かれている。しかしながら、 最近のメモ
       リー管理ハードウェアにより fork(2) と vfork() の間の性能差が 減ったとはいえ、 Linux や他の
       システムで vfork() が残されているのには いくつか理由がある:

       *  性能に厳しいアプリケーションでは、 vfork() により得られる  小さな性能上のメリットが必要
          な場合がある。

       *  vfork()  はメモリー管理ユニット (MMU) を持たないシステムでも実装すること ができるが、そ
          のようなシステムで fork(2) を実装することはできない。 (POSIX.1-2008 では vfork() が標準
          から削除された。  posix_spawn(3) 関数の POSIX の原理 (rationale) には、 fork(2)+exec(3)
          と等価な機能を提供する posix_spawn(3) は、 MMU を持たないシステムでも実装できるように設
          計されたとの注記がある。)

       *  On  systems where memory is constrained, vfork()  avoids the need to temporarily commit
          memory (see the description of /proc/sys/vm/overcommit_memory in proc(5))  in order  to
          execute a new program.  (This can be especially beneficial where a large parent process
          wishes to execute a small helper program in  a  child  process.)   By  contrast,  using
          fork(2)   in  this scenario requires either committing an amount of memory equal to the
          size of the parent process (if strict overcommitting is in  force)   or  overcommitting
          memory with the risk that a process is terminated by the out-of-memory (OOM) killer.

   Caveats
       The child process should take care not to modify the memory in unintended ways, since such
       changes will be seen by the parent process once the child terminates or  executes  another
       program.   In  this  regard,  signal  handlers  can be especially problematic: if a signal
       handler that is invoked in the child of vfork()  changes memory, those changes may  result
       in  an inconsistent process state from the perspective of the parent process (e.g., memory
       changes would be visible in the parent, but changes to the state of open file  descriptors
       would not be visible).

       When  vfork()   is called in a multithreaded process, only the calling thread is suspended
       until the child terminates or executes a new  program.   This  means  that  the  child  is
       sharing an address space with other running code.  This can be dangerous if another thread
       in the parent process changes credentials (using setuid(2)  or similar), since  there  are
       now  two  processes with different privilege levels running in the same address space.  As
       an example of the dangers, suppose that a multithreaded program running as root creates  a
       child  using vfork().  After the vfork(), a thread in the parent process drops the process
       to an unprivileged user in order to run some untrusted code  (e.g.,  perhaps  via  plug-in
       opened  with dlopen(3)).  In this case, attacks are possible where the parent process uses
       mmap(2)  to map in code that will be executed by the privileged child process.

   Linux での注意
       pthread_atfork(3)  を使って設定された fork ハンドラーは NPTL  スレッドライブラリコールを採
       用したマルチスレッドプログラムでは 呼び出されない。一方、LinuxThreads スレッドライブラリを
       使った プログラムでは、fork ハンドラーは呼び出される。 (Linux のスレッドライブラリの説明は
       pthreads(7)  を参照。)

       vfork() の呼び出しは、以下の flags を指定して clone(2) を呼び出す のと等価である。

            CLONE_VM | CLONE_VFORK | SIGCHLD

   歴史
       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 で追加された。

バグ

       シグナルの扱いの詳細は不明瞭でシステムごとに異っている。  BSD  のマニュアルには、 「デッド
       ロック状態になる可能性があるので vfork() の途中の子プロセスに SIGTTOUSIGTTIN  シグナル
       を送信してはならない;  さらに出力や ioctl は許されるが、入力を試みた場合には結果はファイル
       終端 (EOF) になる。」 と書かれている。

関連項目

       clone(2), execve(2), fork(2), unshare(2), wait(2)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。