forkとexecはどのように機能しますか?


17

私はあまり経験がなく、ユーザーレベルからハードウェアにどのように解釈するのかプロセスに関与しようとしています。

そのため、コマンドがシェルから起動されると、そのコマンドのfork()子プロセスを継承し、子プロセスをexec()メモリにロードして実行します。

  1. 子プロセスに親プロセス(元のプロセス)のすべての属性が含まれている場合、この子プロセスの必要性は何ですか?元のプロセスもメモリにロードされている可能性があります。
  2. これforkexec概念は、UNIXのすべての実行可能プログラムに適用されますか?シェルスクリプトも、コマンドだけが好きですか?シェルの組み込みコマンドにも適用されますか?
  3. コマンド/スクリプトを実行する場合、コピーオンライトの概念はいつ使用されますか?

一度に多くの質問をしてすみませんが、コマンドの実行について考えると、これらすべての質問が一度に思い浮かびます。


私はこれが重複しているとは言いませんが、あなたの質問のいくつかはここで答えられていると思います:unix.stackexchange.com/questions/136637 / ...そしてその質問の上部にリンクされている他の答え。
goldilocks

回答:


22

したがって、コマンドがシェルから起動されると、fork()はその子プロセスを継承し、exec()は子プロセスをメモリにロードして実行します。

そうでもない。 fork()現在のプロセスを複製し、同一の子を作成します。 現在のプロセスにexec()新しいプログラムをロードし、既存のプログラムを置き換えます。

私の質問:

子プロセスに親プロセス(元のプロセス)のすべての属性が含まれている場合、この子プロセスの必要性は何ですか?元のプロセスもメモリにロードされている可能性があります。

必要なのは、親プロセスがまだ終了したくないためです。新しいプロセスが実行され、同時に実行を継続すると同時に何かを実行することを望んでいます。

このフォークとexecの概念は、UNIXのすべての実行可能プログラムに適用されますか?シェルの組み込みコマンドにも適用されますか?

外部コマンドの場合、シェルはfork()コマンドを新しいプロセスで実行するようにします。ビルトインはシェルによって直接実行されます。もう1つの注目すべきコマンドはexecexec()最初にfork()ing せずにシェルに外部プログラムに指示するコマンドです。これは、シェル自体が新しいプログラムに置き換えられるため、そのプログラムが終了時に戻るためにシェルが存在しないことを意味します。あなたが言う場合は、exec true、その後、/bin/trueそれが終了しますので、もうあなたの端末で実行して何も残さない、自分の殻を交換し、すぐに終了します。

コマンド/スクリプトを実行する場合、コピーオンライトのコンセプトが使用されますか?

石器時代に戻って、fork()実際には呼び出しプロセスのすべてのメモリを新しいプロセスにコピーする必要がありました。コピーオンライトは、2つのプロセスが同じメモリの共有を開始するようにページテーブルが設定され、いずれかのプロセスによって書き込まれたページのみが必要なときにコピーされる最適化です。


4
「ほとんどすべてのコマンドについて、シェルはfork()を実行するため、コマンドは新しいプロセスで実行されます。そのコマンドが組み込みコマンドである場合、子は別のプログラムをexec()する必要はありません。」良い答えですが、この部分は編集する必要があります。組み込みコマンドの実行時にシェルは分岐しません。これらはアクティブなシェルプロセスで直接実行されます。これは、ビルトインが好むcdまたは機能する唯一の方法readです。フォークがないため、組み込みコマンドは外部コマンドよりもはるかに高速になります。
ジョンクーゲルマンはモニカをサポートします

6
  1. 一部のプログラムでは、子プロセスは1つのこと(シリアルポートからの読み取り、端末への書き込み)を行い、親プロセスは他の何か(端末からの読み取り、シリアルポートへの書き込み)を続けます。別の典型的な例は、子プロセスが長時間実行されている計算のチェックポイントを実行することです。ほとんどの場合、子プロセスは、ディレクトリの変更、シグナルハンドラのリセット、ファイル記述子のリセットなどのセットアップを行い、その後execve()、別のコードで自分自身をオーバーレイするために呼び出します。
  2. fork()そしてexec()、すべての実行可能ファイルには適用されない-実際には、argcおよびargvの、およびパイプと一緒に、フォークとexecは、他のオペレーティングシステムからのUnixを区別するものです。fork()BSD vfork()、Plan 9 rfork()、Linuxなど、いくつかの特殊化または一般化が存在しますclone()が、原則は同じです。
  3. 「書き込み時コピー」は実際にはユーザーには表示されません。子プロセスの作成を最適化し、実行中に最適化する手法です。コールスタックとヒープ(で割り当てられたメモリmalloc()、または静的またはグローバルスコープ変数)は、「コピー時に書き込み」になる場合があります。子プロセスがfork()呼び出し、カーネルは、子プロセスをセットアップして、親プロセスとまったく同じメモリページをヒープおよびスタックとして保持します。ハードウェア(メモリ管理ユニット)がヒープまたはスタックの書き込みを検出すると、カーネルはメモリの新しい物理ページを取得し、親のページを新しいページにコピーし、その新しいページを子プロセスのスタックまたはヒープにマッピングします。これは、カーネルが子プロセスのスタックとヒープを完全にコピーするよりもページマッピングのセットアップにかかる時間が少ないため、最適化を構成します。

ブルースに答えてくれてありがとう。しかし、あなたがここで言った多くのことは、私の頭上で起こっています。私はこれらのことについてあまり知識を持っていません。あなたが言及したこれらの機能を動作させようとします。どうもありがとうございます..!!
PriB

4
子プロセスに親プロセス(元のプロセス)のすべての属性が含まれている場合、この子プロセスの必要性は何ですか?元のプロセスもメモリにロードされている可能性があります。

この質問は、厳しいメモリ制約の下で動作する必要があり、一度にメモリ/アドレス空間で実行するプロセスが1つだけであった初期のUnix実装を見ると非常にわかりやすく答えられています。

マルチタスクは、プロセスをディスクにスワップアウトし、別のプロセスをスワップインすることで達成されました。

これでforkシステムコールはほぼ同じになりました。プロセスをディスクにスワップアウトしましたが、別のプロセスをスワップインする代わりに、インメモリコピーに別のプロセスIDを与えてそこに戻りました。そして、それはこのプロセスがexec結局別の実行可能ファイルに進むことを決定するのに都合の良い時点でした。

fork+ execこのように、実際にはスポーンで顕著なオーバーヘッドは発生しませんでした。とにかくプロセスをディスクにスワップアウトする必要があり、古いプロセスイメージは実行可能なメモリの場所にありました。

使用可能なメモリとメモリ管理ユニットの量が増え、複数のインメモリプロセスが発生したため、最初は無視できるほどのコストが一部のアーキテクチャにとってはやや厄介になりvforkました。


2

これをできるだけわかりやすくするために、類推を使用します。パイを焼きましょう!

レシピ本を手に取り、読み始めて、手作りの皮付きのイチゴルバーブパイ(私のお気に入り)に落ち着きます。私たちが必要とするほぼすべてのものは、卵と果物を除いてキッチンにありますが、私たちは農場に住んでおり、果物は季節にあるので、これは問題ではありません。問題は、オーブンが壊れており、すべてのことを行うのに十分な時間がないことです。私が複数いるのはいいことではないでしょうか?

fork()が助けになります。今私は二人います。そして私たち二人ともキッチンに行ってパイ生地を作り始めます。おっとっと。そこで、フォークからの戻りを見てみましょう。私は彼がゼロになった大きな数を手に入れたので、彼が鶏小屋と庭に向かう間、私は台所に向かいます。オーブンを通り過ぎると、私は再びfork()し、戻り値を見てください。壊れたオーブンを見つめながら、彼は小麦粉を食べ続けます。ドアを開ける、明かりなし、ドアを閉める。誰でもオーブンを修正する方法を知っていますか?

exec()が助けになります。ツールベルトの電圧計に手を伸ばすと、電球が診断できるので、電源をチェックします。ブレーカーパネルに向かって歩くと、仲間がルバーブを摘んでいるのが見えます。うん!私はチョコレートシルクパイが好きです。

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