fork()とvfork()の違いは何ですか?


13

fork()とvfork()の違いを詳細に理解したいと思います。マニュアルページを完全に消化できませんでした。

また、同僚のコメントの1つを明確にしたいと思います。「現在のLinuxにはvfork()はありません。たとえそれを呼び出しても、内部的にfork()を呼び出します。」

回答:


24

通常、マニュアルページは簡潔なリファレンスドキュメントです。ウィキペディアは、概念的な説明を参照するのに適した場所です。

Forkはプロセスを複製します。親プロセスとほとんど同じ子プロセスを作成します(最も明らかな違いは、新しいプロセスのプロセスIDが異なることです)。特に、forkは(概念的に)すべての親プロセスのメモリをコピーする必要があります。

これはかなりコストがかかるため、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呼び出し時にはコピーされませんが、後で親または子が最初にページに書き込むときにコピーされます。つまり、各ページは共有として開始され、いずれかのプロセスがそのページに書き込むまで共有されたままになります。書き込みを行うプロセスは、新しい物理ページを取得します(同じ仮想アドレスを使用)。Copy-on-writeを使用すると、vforkはほとんど使用できなくなります。使用可能なfork場合にvforkはコピーが作成されないためです。

Linuxはvforkを保持します。forkシステムコールはまだそれが実際のメモリをコピーしていない場合でも、プロセスの仮想メモリテーブルのコピーを作成する必要があります。vforkこれをする必要さえありません。ほとんどのアプリケーションでは、パフォーマンスの向上はごくわずかです。


1
このすばらしい回答をありがとう.. fork()を実行している間、子はとにかく新しいプロセスIDとそれに関連付けられた仮想スペースを取得しようとしています。私はその部分で明確ではありません。
セン

@Sen:fork後続のコピーオンライトコピーが2つのプロセスのうちの1つだけに影響するように、個別の仮想メモリマッピングを作成する必要があります。
ジル 'SO-悪であるのをやめる'

親プロセスが実行されていると確信していますか?
qbolec 14年

2

fork()そしてvfork()システムコールが異なります。

fork()システムコールは、別個のメモリを持つ2つの同一のプロセスを生成します。vfork()システムコールは、同じメモリを共有する2つのプロセスを生成します。

ではvfork()、親、子が終了するのを待ちます。親は、プログラムが共有している変数を継承します。したがって、子が呼び出された後、子の内部で変更されたすべての変数は、親の内部で引き続き変更されます。

詳細については、ここをクリックしてください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.