Fork()とvfork()の違いを詳しく理解したいと思います。マニュアルページを完全に消化できませんでした。
また、同僚のコメントの1つを明確にしたいと思います。「現在のLinuxでは、vfork()はありません。呼び出しても、内部的にfork()を呼び出します。」
マニュアルページは通常、簡潔なリファレンスドキュメントです。 Wikipedia は、概念的な説明を参照するのに適した場所です。
Forkはプロセスを複製します。親プロセスとほぼ同じ子プロセスが作成されます(最も明らかな違いは、新しいプロセスのプロセスIDが異なることです)。特に、フォークは(概念的に)すべての親プロセスのメモリをコピーする必要があります。
これはかなりコストがかかるため、vforkはコピーが不要な一般的な特殊なケースを処理するために発明されました。多くの場合、子プロセスが最初に行うのは、新しいプログラムイメージを読み込むことです。そのため、次のようになります。
if (fork()) {
# parent process …
} else {
# child process (with a new copy of the process memory)
execve("/bin/sh", …); # discard the process memory
}
execve
呼び出しは新しい実行可能プログラムをロードし、これはプロセスのコードとデータメモリを新しい実行可能プログラムのコードと新しいデータメモリに置き換えます。したがって、fork
によって作成されたメモリコピー全体は、まったく無駄でした。
したがって、 vfork
呼び出しが発明されました。メモリのコピーは作成しません。したがって、vfork
は安価ですが、子プロセス内のプロセスのスタックまたはヒープ領域にアクセスしないようにする必要があるため、使いにくいです。親プロセスは実行を続けるため、読み取りでさえ問題になる可能性があることに注意してください。たとえば、次のコードは機能しません(子または親が最初にタイムスライスを取得するかどうかによって、機能しない場合があります)。
if (vfork()) {
# parent process
cmd = NULL; # modify the only copy of cmd
} else {
# child process
execve("/bin/sh", "sh", "-c", cmd, (char*)NULL); # read the only copy of cmd
}
Vforkの発明以来、より良い最適化が発明されました。 Linuxを含む最近のほとんどのシステムでは、 copy-on-write の形式を使用しています。この場合、プロセスメモリ内のページはfork
の呼び出し時にコピーされませんが、後で親または子が最初にページに書き込みます。つまり、各ページは共有として開始され、いずれかのプロセスがそのページに書き込むまで共有されたままになります。書き込みを行うプロセスは、(同じ仮想アドレスを持つ)新しい物理ページを取得します。 fork
はvfork
が使用可能な場合にコピーを作成しないため、コピーオンライトではvforkがほとんど役に立たなくなります。
Linuxはvforkを保持します。 fork
システムコールは、実際のメモリをコピーしなくても、プロセスの仮想メモリテーブルのコピーを作成する必要があります。 vfork
はこれを行う必要さえありません。ほとんどのアプリケーションでは、パフォーマンスの向上はごくわずかです。
fork()
とvfork()
のシステムコールは異なります。
fork()
syscallは、別々のメモリを持つ2つの同一のプロセスを生成します。 vfork()
syscallは、同じメモリを共有する2つのプロセスを生成します。
vfork()
を使用すると、親は子が終了するのを待ちます。親は、プログラムが共有している変数から継承します。したがって、子が呼び出された後、子の内部で変更されたすべての変数は、親の内部でも変更されます。
詳細については ここ をクリックしてください