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/ に書かれている。