web-dev-qa-db-ja.com

Windows OSはどのようにしてプロセスの仮想メモリを追跡しますか?

背景:したがって、最近のオペレーティングシステムでは、プロセスには基本的に完全な32ビット(または64ビット)のアドレス空間があります。私の知る限り、プロセスの実際の仮想メモリアドレスは、最初にプログラムの.exeファイルに保存されます。つまり、リンカはすべての関数参照と変数を0x00007fb6などの実際のアドレスでパッチします。私の理解では、これらの仮想アドレス(またはローダーのために変更されたバージョン)は、最終的にRAM内の実際の物理アドレスにマップできます。

問題:私の質問は、作成者がプログラムの仮想アドレス空間に何かをマッピングするようなことについて話すときです。マッピングファイルの内容、それらは正確にはどういう意味ですか? OSが.exeから個々のプロセスの仮想アドレスを取得することを概念化できる限り、別のファイルのコンテンツがそのプロセスの仮想アドレス空間にマップされていた場合、それらのコンテンツはexeファイルに保存されますか?それとも、OSは追加されたコンテンツを舞台裏で追跡しているだけですか?

2
Boagz

まず、この種のことを深く掘り下げたい場合は、 Windows Internals、Part 1:System Architecture、Processes、Threads、Memory Management、and more、7th Edition のコピーを入手することを強くお勧めします。 =。それは詳細を説明するのに良い仕事をします。または、たとえば Linuxドキュメント 、これはより一般に公開されています-少し異なりますが、Windowsと同じ概念の多くに従います。

ここ もう1つのおそらくよりアクセスしやすい説明です。

ページテーブル がどのように機能するか、そしておそらく TLB も確認することをお勧めします。


その要点は、プロセスが仮想アドレス空間の特定のページに対して読み取りまたは書き込みを試みると、CPUのメモリ管理ユニット(MMU)がそれを物理アドレスに変換することです。アドレス(TLBを介してページテーブルを確認することにより、ページテーブルエントリ専用の特別なオンチップキャッシュ)、またはページテーブルエントリに「ページが存在しません」と表示されている場合は、オペレーティングシステムに通知します。これは、ページフォールトと呼ばれるものです。 OSに応答して、a)必要に応じて、新しい物理ページをプロセスに割り当て、そのコンテンツを「バッキングストア」(ページファイルまたはマップファイル)からRAMのそのページにロードします。b)ページテーブルエントリを更新して、物理ページを反映します。ページのアドレス、およびc)CPUに再試行するように指示します(「ページフォールトを却下します」)。

定義された仮想アドレス空間のページごとにページテーブルエントリがあります。ページテーブルエントリは、CPUがアドレス変換を実行するために使用するだけではありません。 「無効な」ページに対応するPTE(アクセス時にページフォールトが発生するPTE)は、ページのデータの場所に関する情報を格納するためにOSによって使用されます。したがって、PTEは、定義されたすべての仮想アドレスに対して存在します。サブセットは通常「有効」です。つまり、ページフォールトなしでアクセスできる仮想アドレスに対応します。 (このサブセットは、プロセスの「ワーキングセット」と呼ばれます。)

「無効な」ページのPTEには、そのページに障害が発生した場合にOSがページのコンテンツを検出できるようにする情報が含まれています。コンテンツは、ページファイル、マップファイル、RAM(ページキャッシュの1つ)、別のプロセスのワーキングセット(共有ページの場合)、またはまったくない場合があります。 (初期コンテンツが定義されておらず、まだ参照されていないページの場合。このようなページは単に物理的に割り当てられ、最初の参照時にゼロで埋められます。これらのイベントは「デマンドゼロページフォールト」と呼ばれます)。

ページテーブルは大きすぎて(非常に小さい)TLBに完全に収まらないため、通常のメモリに格納されます。

実際、ページテーブルは大きすぎてRAMに一度に収まらないため、プロセスごとにツリー構造に編成され、各ツリーの最上位テーブルを除くすべてがそれ自体でページング可能です。

一般的な最新のOSでは、各プロセスに独自のページテーブルがあり、プロセスのアドレス空間が互いに独立しています。カーネルは、自身のメモリ領域内のプロセスとそのアドレス空間を追跡します。現在のWindowsでは、これは他のプロセスメタデータとともに、メモリ内の「EPROCESS」データ構造および仮想アドレス記述子と呼ばれる関連構造に格納されます。 Windowsは、独自のカーネルモードコードとデータ用に個別のページテーブル構造も維持しています。

これは覚えておくことが重要です。プロセスのアドレス空間は純粋にメモリに格納され、プロセスが起動された実行可能ファイル+ DLLに書き戻されることはありません。プロセスが終了すると、アドレス空間は破棄されます。ただし、書き込みアクセス用に開かれたマップファイルへの変更は、それぞれのファイルにフラッシュバックされます。


私の知る限り、プロセスの実際の仮想メモリアドレスは、最初にプログラムの.exeファイルに保存されます。つまり、リンカはすべての関数参照と変数を0x00007fb6などの実際のアドレスでパッチします。

いいえ。これはプログラムコードへの参照のみです。プロセスのアドレス空間には、2つ以上のヒープ、すべてのスレッドのスタック、およびプロセスのスレッドが実行時に作成する追加のアドレス範囲も含まれます。

そして最近では、プログラムコードでさえロード時に(ランダムに)再配置されます。これはASLRと呼ばれ、特定の種類の攻撃を困難にします。

私が概念化できる限り、OSは.exeから個々のプロセスの仮想アドレスを取得します

いいえ。実行可能ファイルは、一部の初期データの場所のみを指定します。つまり、プログラムコード、グローバル変数、およびリンクライブラリです。そして、この情報の多くでさえ、最新のOSではASLRによって上書きされます。

その他のメモリ(プログラムヒープ、スレッドスタック、マップファイルなど)は、プログラムによって動的に割り当てられます。サイズ、場所などは、プログラムの実行中に変更される可能性があります。

上記のように、各プロセスには独自の独立した仮想アドレス空間があります。その一部はカーネルメモリ(ユーザーモードから読み取りまたは変更不可とマークされている)にマップされますが、残りはプロセス専用です。プロセスのアドレス空間は、明示的に要求されない限り(「共有メモリ」)、またはパフォーマンスのために完全に透過的に実行されない限り(コピーオンライト、マップファイル)、他のプロセスと共有されません。

図5-10x86仮想アドレス空間レイアウト(左側に2 GB、右側に3 GB) Windows Internals、Part 1 :システムアーキテクチャ、プロセス、スレッド、メモリ管理など、第7版 は、一般的なプロセスアドレス空間のレイアウトを示す優れた図です。残念ながら、ここで複製することは許可されていません。

したがって、別のファイルのコンテンツがそのプロセスの仮想アドレス空間にマップされていた場合

これは、マップされたファイルからデータをロードするようにOSに指示するプロセスのページテーブルの特別なエントリとして終了します。これは事実上リダイレクトです。 「他の場所を見る」。アドレス空間はvirtualであることに注意してください。ファイルを参照している可能性がありますが、そのファイルはスレッドが読み取り/書き込みを試みるまでロードされません。それでも、一度に1ページまたは数ページしか読み込まれません。

次に、それらのコンテンツはexeファイルに保存されます。

いいえ。実行可能ファイルは常に読み取り専用でロードされます。ロードされると、すべての関連情報は純粋にメモリに保存され、OSによって「保存」されることはありません。マップされたファイルまたは共有メモリへの書き込みを除いて、プロセスが終了すると、プロセスメモリへの変更はすべて失われます。

それとも、OSは追加されたコンテンツを舞台裏で追跡しているだけですか?

はい、どのリージョンがどのファイルにマップされているかがプロセスメタデータで追跡されます。

3
Bob