プロセスを生成するためのUNIXシステムコールfork()は、親プロセスをコピーして子プロセスを生成します。私が理解することは、ほとんどの場合、子プロセスのメモリ空間(テキストセグメントを含む)を置き換えるためにexec()を呼び出すことに従うことです。 fork()から親のメモリスペースをコピーすることは私にとって常に無駄なようです。 (メモリセグメントを書き込み中にコピー(つまり、ポインタのみコピー)することで無駄を最小限に抑えることができることを知っていますが)。とにかく、プロセスの作成にこのような反復的なアプローチが必要な理由を知っている人はいますか?
答え1
インターフェイスを簡素化することです。fork
交換はexec
Windowsに似ています。プロセスの作成機能。どのくらいのパラメータがあるかを確認してくださいCreateProcess
。その多くは、より多くのパラメータを持つ構造です。このためですすべて新しいプロセスのための制御権CreateProcess
。CreateProcess
ユーザーによるプロセスの作成そしてログインを使用したプロセスの作成。
このfork/exec
モデルでは、これらのパラメータはすべて必要ありません。代わりに、プロセスの一部のプロパティがに保存されますexec
。これにより、fork
必要なプロセス属性を変更できます(通常使用するのと同じ機能を使用)。それから exec
。 Linuxにはパラメータがなく、実行するプログラム、そのプログラムに提供されるコマンドライン、および環境の3つしかfork
ありません。execve
(他の関数もありますが、一般的なユースケースを単純化するためにCライブラリが提供するラッパーexec
だけです。)execve
別の現在のディレクトリを使用してプロセスを開始したい場合 :fork
、、、。chdir
exec
stdin/stdout: をリダイレクトするには、fork
ファイルを閉じるか開きますexec
。
ユーザーを切り替えるには:fork
、、、setuid
。exec
これらすべては必要に応じて組み合わせることができます。誰かが新しいプロセス属性を思いついたら、およびfork
を変更する必要はありませんexec
。
Larskが述べたように、ほとんどの最新のUnixは書き込み中にコピーを使用するため、fork
関連するオーバーヘッドはあまりありません。
答え2
cjmの答えに加えて、Single Unix仕様ではvfork()
。この関数はexec関数系列を呼び出すか_exit()
。
したがって、動作定義の唯一の用途は次のとおりです。
pid_t ret = vfork();
if(ret == 0)
{
exec(...);
_exit(EXIT_FAILURE); //in case exec failed for any reason.
}
それで、それは何をしますかvfork
?それは安いですfork
。書き込み中にコピーのない実装で作成されたプロセスは、元のプロセスとメモリスペースを共有します(したがって、未定義の動作)。書き込み中のコピー実装では、書き込み中のコピー実装が高速であるため、vfork
同じことが許可されます。fork()
新しいプロセスを直接生成するオプションのposix_spawn
関数(および関数)もあります。posix_spawnp
(fork
また、ライブラリ呼び出しを使用して実装することもでき、サンプルexec
実装も提供されています。)