マニュアルページからvfork()
:
vfork() は、子プロセスが execve(2) または _exit(2) を呼び出すまで親プロセスが一時停止されるという点で fork() とは異なります。子プロセスは、execve()を実行するまでスタックを含む親プロセスとすべてのメモリを共有します。子プロセスは現在の関数から返すか、exit()を呼び出すべきではありませんが、_exit()を呼び出すことはできます。
_exit()
なぜ子供たちは単にcallの代わりにanを使うべきですかexit()
?この機能がvfork()
で動作することを願っていますfork()
。
答え1
〜のように早く会いました。、vfork
子プロセスが親プロセスのメモリにアクセスすることを許可しません。exit
Cライブラリ関数です(だからよく使うのようにexit(3)
)。 Cストリームのフラッシュとクローズ(で宣言された関数を介してファイルを開くstdio.h
)、に登録されているカスタム関数の実行など、さまざまなクリーンアップ操作を実行しますatexit
。これらの操作にはすべてプロセスメモリへの読み書きが含まれます。
_exit
クリーンアップせずに終了します。これは直接的なシステムコール(それで作成された_exit(2)
)であり、通常はシステムコール番号をプロセッサレジスタに入れ、特定のプロセッサ命令を実行(システムコールハンドラに分岐)することによって実装されます。これはプロセスメモリにアクセスする必要がないため、後で実行しても安全ですvfork
。
その後、fork
そのような制限はありません。これで、親プロセスと子プロセスが完全に自律的になります。
答え2
exit
登録された関数を呼び出してatexit
コピーされた部品の外側のデータにアクセスするなど、追加のクリーンアップを実行します。_exit
システムコールはクリーンアップせずに直接実行されます(カーネル内を除く)。
答え3
子プロセスが終了したときにstdio(または他の)バッファをフラッシュするのを防ぐために、子プロセス呼び出し_exit()があります。子プロセスは親プロセスの正確なコピーを構成するので、子プロセスはまだ親プロセスが「stdout」または「stderr」に持っていたもの、つまり<stdio.h>のバッファを持ちます。子プロセスのatexitハンドラで1つ、親プロセスから1つ(親プロセスのバッファがいっぱいでフラッシュされた場合)を呼び出して、二重出力を取得できます(不適切な場合)。
上記の回答はstdio.hの詳細に焦点を当てていますが、上記の回答のいずれかでわかるように、アイデアは他のバッファリングされたI / Oにも適用できます。
答え4
exit()
:- i/o ストリームを閉じるなど、いくつかのクリーンアップを実行してカーネルに戻ります。
_exit()
:- クリーンアップを行わずにカーネルに直接移動します。
fork()
:親と子の両方に異なるファイルテーブルがあるため、子の変更は親の環境パラメータに影響を与えず、その逆も同様です。
vfork()
:親プロセスと子プロセスは同じファイルテーブルを使用するため、子プロセスの変更は親プロセスの環境パラメータに影響します。たとえば、子プロセスによって変数がvar=10
実行され、親プロセスが実行されている場合は、親プロセスの出力でもその効果を見ることができますvar++
。var++
私が言ったように、exit()
inを使用すると、vfork()
すべてのI / Oはすでに閉じられています。したがって、親プロセスが正しく実行されても、すべての変数がフラッシュされ、すべてのストリームが閉じられるため、正しい出力が得られません。