web-dev-qa-db-ja.com

2つの同一の仮想アドレスが異なる物理アドレスを指すにはどうすればよいですか?

Linuxでfork()を呼び出した後、2つのプロセス(一方は他方の子)が割り当てられたヒープメモリを共有します。これらの割り当てられたページはCOW(コピーオンライト)とマークされ、いずれかのプロセスがそれらを変更するまで共有されたままになります。この時点で、それらはコピーされますが、それらを参照する仮想アドレスポインタは同じままです。 MMU(メモリ管理ユニット)は2つをどのように区別できますか?次のことを考慮してください。

  1. プロセスAが開始されます
  2. プロセスAには、仮想アドレス0x1234が指すメモリページが割り当てられます。
  3. プロセスAfork()s、スポーンプロセスB
  4. プロセスAとBは、同じ物理メモリ位置を指す仮想アドレス0x1234を共有するようになりました。
  5. プロセスBは0x1234メモリページを変更します
  6. このメモリページはコピーされてから変更されます
  7. プロセスAとBは両方とも仮想アドレス0x1234を持っていますが、これは異なる物理メモリアドレスを指しています

これはどのように区別できますか?

4
notlesh

プロセス間のコンテキスト切り替え中にカーネルが行うことの1つは、MMUテーブルを変更して、前のプロセスのアドレス空間を説明するエントリを削除し、次のプロセスのアドレス空間を説明するエントリを追加することです。プロセッサアーキテクチャ、カーネル、場合によっては構成では、これはプロセッサレジスタを変更するか、メモリ内のページテーブルを操作することで実行できます。

フォーク操作の直後、コピーオンライトにより、両方のプロセスのMMUテーブルは仮想アドレス0x1234に対して同じ物理アドレスを持ちます。ここでも、これらは2つの別個のテーブルです。この特定の仮想アドレスに対して、たまたま同じエントリがあります。

このページの記述子には、読み取り専用属性があります。プロセスが書き込もうとすると(AかBかは関係ありません)、パーミッション違反が原因でプロセッサ障害が発生します。カーネルのページフォールトハンドラーが実行され、状況が分析され、新しい物理ページの割り当てが決定され、読み取り専用ページのコンテンツがこの新しいページにコピーされ、呼び出しプロセスのMMU構成が変更され、次のようになります。 0x1234は、読み取り/書き込み属性を持つこの新しく割り当てられた物理ページを指し、フォールトの原因となった命令で呼び出しプロセスを再開します。今回は、ページが書き込み可能であるため、命令はトラップされません。

他のプロセスのページ記述子は、この操作の影響を受けないことに注意してください。実際、カーネルがもう1つのアクションを実行するためである可能性があります。ページが単一のプロセスでのみマップされるようになった場合、後でコピーする必要がないように、読み取り/書き込みに切り替えられます。

参照 ページフォールト後に何が起こりますか?