3

私は、fork()関数がその親と同一のプロセスを作成することを知っていますが、それが持つPIDによってのみ異なります。それらは最初は同じ変数を持っており、これらの変数に加えられた変更は互いに影響しません。しかし、グローバルポインタ変数が共有されるとどうなりますか?

私はいくつかのコードを書き、結果を印刷しました。親プロセスと子プロセスには同じメモリ位置を指すポインタがあるように見えますが、これらのメモリ位置に加えられた変更、つまり*p = 1親と*p = 2子での変更は相互に影響しません。wait(NULL)また、子プロセスが終了するまで親プロセスを作成することにも注意してください。したがって、子プロセスは、親プロセスのポインタと同じメモリアドレスを持つポインタが指す値を変更します。

いつfork()呼び出されるかはわかっていますが、親プロセスはレジスター、プログラムカウンターなど、すべてのクローンを作成します。しかし、それはどのようにして可能でしょうか。子プロセスが終了した後、親プロセスの変数の値を変更するべきではありませんか?システムがすべて(親プロセスのポインタ変数を含む)をスタックに置き、子が終了したときにそれらをポップするためですか?

4

2 に答える 2

4

プロセスがフォークされると、新しいプロセスはすべての(?)意図と目的のために、独自の仮想アドレス空間、ファイル記述子などを持つ元のコピーになります.かなり単純化した見方では、同じメモリアドレスは実際には別のメモリアドレスを指します.各プロセスの物理メモリ アドレス - 完全に異なるデータを指す 2 つの等しいポインターを持つことができます。

当然のことながら、最新のオペレーティング システムでは、物事はそれほど単純ではありません。fork()たとえば、プロセッサ時間とメモリの両方が無駄になるため、実際にはすべてをコピーするわけではありません。カーネルは、ページ テーブル操作を少し利用して、コピー オン ライトメモリの複製を実装します。さらに、パフォーマンスと正確性の両方の理由から、子プロセスに実際に複製されるリソースをある程度制御することができます。

于 2013-03-09T20:49:30.930 に答える
2

これは非常に大きなトピックですが、簡単に説明します。実行スレッドとフォークされたプロセスを混同している可能性があります。Unix システムでは、各プロセスは独立しており、独自の仮想アドレス空間を持っています。これは、同じアドレスに設定されたポインタを持つ 2 つのプロセスが、実際には通常、物理メモリ内の異なるアドレスを使用していることを意味します。この概念は、まともなオペレーティング システムの不可欠な部分です。より原始的なものでは、実行中のプログラムは物理メモリに直接アクセスできます。実際、実行可能ファイルの 1000 のインスタンスを一度に実行した場合、それぞれがすべてに対してまったく同じアドレスを使用していることに気付くでしょう。

これによるセキュリティ上の利点とは別に、プログラムの「テキスト」部分 (バイナリ命令) を実行中のプログラムのすべてのインスタンスで共有することもできます。カーネルは、すべてのプロセスを物理メモリ内の同じアドレスにマップできます。

子が親の正確なコピーである、またはすべてを共有しているというのは真実ではありません。継承されるものと継承されないものの長いリストがあります。ほとんど同じです。同じ実行可能コード、同じ開いているファイルなどがありますが、完全に独立した別のプロセスです。

于 2013-03-09T20:51:36.060 に答える