Unixでは、新しいプロセスを作成するたびに現在のプロセスを分岐し、親プロセスとまったく同じ新しい子プロセスを作成し、execシステムコールを実行して親プロセスのすべてのデータを次に置き換えます。新しいプロセスデータ。
新しいプロセスを直接作成するのではなく、まず親プロセスのコピーを作成するのはなぜですか?
答え1
短い答えはfork
Unixです。その理由は、当時の既存システムに容易に適していたからです。バークレーの全身システムフォークという概念が使用されます。
~からUnix時分割システムの進化(関連テキストは最も明るい部分):
近代的な形式のプロセス制御は、数日以内に設計され実装されています。既存のシステムにどれだけ簡単に適用できるかは驚くべきことです。デザインのわずかに珍しい特徴のいくつかは、既存のコンテンツに対するコンパクトでコーディングしやすい変更を示すため、正確に現れました。。良い例は、フォークと実行機能の分離です。新しいプロセスを生成する最も一般的なモデルには、実行するプロセスを指定するプログラムが含まれます。 Unix で分岐したプロセスは、明示的な実行を実行するまで親プロセスと同じプログラムを実行し続けます。機能の分離は確かにUnixに限定されているわけではなく、実際、トンプソンが知っていたバークレー時分割システムにも存在していた。。それにもかかわらず仮定するのが妥当に見える。フォークは他に何も変更せずに簡単に実装できるため、Unixに存在します。。システムは複数(たとえば2つ)のプロセスを処理しました。プロセステーブルがあり、プロセスはメインメモリとディスク間で交換されます。最初はフォークの実装だけが必要です。
1) プロセステーブルの拡張
2)既存のスワップIOプリミティブを使用して、現在のプロセスをディスクスワップ領域にコピーするフォークコールを追加し、プロセステーブルをいくつか調整しました。
実際、PDP-7のフォークコールには正確に27行のアセンブリコードが必要です。もちろん、オペレーティングシステムやユーザープログラムへの他の変更も必要でしたが、そのいくつかは非常に興味深く予想外のものでした。しかし、結合されたフォークの実行はより複雑です。、exec自体が存在しないため、その機能は明示的なIOを使用してシェルですでに実行されています。
その論文の後、Unixは発展を続けてきました。fork
2番目は、もはやexec
プログラムを実行する唯一の方法ではありません。
フォークより効率的なフォークで作成され、新しいプロセスがフォークの直後にexecを実行しようとするときに使用されます。 vforkが実行されると、親プロセスと子プロセスは同じデータスペースを共有し、子プロセスがプログラムを実行または終了するまで、親プロセスは一時停止されます。
posix_spawn単一のシステムコールで新しいプロセスを作成し、ファイルを実行します。複数のパラメータを使用し、発信者が開いたファイルを選択的に共有し、そのシグナリング構成およびその他の属性を新しいプロセスにコピーできます。
答え2
[私の答えの一部を繰り返します。ここ.]
最初から新しいプロセスを生成するコマンドを使用するとどうなりますか? すぐに交換されるものをコピーすることはとんでもなく非効率的ではないでしょうか?
実際、これは次のようないくつかの理由でそれほど効果的ではない可能性があります。
fork()
カーネルが使用するように、結果の「コピー」はやや抽象的です。書き込み中のコピーシステム;実際に作成する必要があるのは仮想メモリマップだけです。 copy が直ちに呼び出される場合exec()
、プロセスのアクティビティがデータを変更してもほとんどのデータは実際にコピー/生成される必要はありません。プロセスは、データの使用に必要な操作を実行しないためです。サブプロセスの重要な側面(たとえば、その環境)は、個別にコピーしたり、コンテキストなどの複雑な分析に基づいて設定する必要はありません。彼らは呼び出しプロセスと同じであると仮定し、これは私たちになじみのあるかなり直感的なシステムです。
#1をより詳細に説明すると、「コピー」されたがアクセスされていないメモリは、少なくともほとんどの場合、実際にはコピーされません。この場合は例外があります可能プロセスを分岐する場合は、子プロセスがそれを置き換える前に親プロセスが終了するようにしてくださいexec()
。私は言った可能利用可能なメモリが十分であれば、ほとんどの親がキャッシュされる可能性があるため、これがどの程度悪用されるかはわかりません(OSの実装によって異なります)。
もちろん、表面的にこれはコピーを使用するという意味ではありません。もっと空のスレートを使用するよりもはるかに効率的です。ただし、「空のスレート」は実際には何もなく、割り当てが必要です。システムは1と同じ方法で複製する通常の空/新しいプロセステンプレートを持つことができますが、記録中のコピーブランチに比べて実際には何も保存しません。したがって、#1は、「新しい」空のプロセスを使用する方が効率的ではないことを証明します。
ポイント2では、フォークを使用する方が効率的な理由を説明します。子環境は、まったく異なる実行可能ファイルであっても親環境から継承されます。たとえば、親プロセスがシェルで子プロセスがWebブラウザである場合は、$HOME
まだ同じですが、どちらも後で変更できるため、2つの別々のコピーにする必要があります。ボックスにあるのがオリジナルですfork()
。
1. この戦略は文字通り理解できないかもしれませんが、私の要点は、プロセスを作成するにはディスクからメモリにイメージをコピーする以上のものが含まれていることです。
答え3
fork
Unixが新しいプロセスを作成する能力しか持っていない理由は次のとおりです。Unixの哲学
彼らは1つのことを非常にうまく実行する機能を構築します。子プロセスを作成します。
新しいプロセスを処理する方法はプログラマに依存します。彼はexec*
関数の1つを使用して別のプログラムを起動することができます。あるいは、execを使用し、同じプログラムの2つのインスタンスを使用することはできません。これは便利です。
したがって、次のものを使用できるため、より多くの自由を得ることができます。
- execのないフォーク*
- exec*を使用したフォークまたは
- フォークなしでただ実行*
さらに、1970年代にやらなければならなかった呼び出しを覚えfork
て機能するだけです。exec*
答え4
fork()関数は親プロセスをコピーするだけでなく、そのプロセスが親プロセスか子プロセスかを示す値も返します。下の画像は、親プロセスと子プロセスでfork()を使用する方法を示しています。息子:
図に示すように、fork()はプロセスが親プロセスの場合は子プロセスIDを返しPID
、それ以外の場合は返します。0
たとえば、要求を受信するプロセス(Webサーバー)があり、各要求に対してその要求を処理するプロセスを作成する場合は、この方法を使用できます。son process
ここで父と息子は異なる仕事をします。
したがって、プロセスコピーを実行しないことはfork()とは異なります。