プロセッサは、メモリの場所に対する読み取りまたは書き込み時に仮想アドレスを使用します。 これらの操作中に、プロセッサは仮想アドレスを物理アドレスに変換します。
仮想アドレスを使用してメモリにアクセスするには、いくつかの利点があります。
プログラムは、連続した範囲の仮想アドレスを使用して、物理メモリ内の大きな連続しないメモリ バッファーにアクセスできます。
プログラムは、一連の仮想アドレスを使用して、使用可能な物理メモリより大きいメモリ バッファーにアクセスできます。 物理メモリが少ない場合、メモリ マネージャーは物理メモリのページ (通常は 4 KB のサイズ) をディスク ファイルに保存します。 システムは、必要に応じて、物理メモリとディスクの間でデータまたはコードのページを移動します。
さまざまなプロセスで使用される仮想アドレスは分離されます。 あるプロセスのコードは、別のプロセスまたはオペレーティング システムによって使用されている物理メモリを変更できません。
プロセスで使用できる仮想アドレスの範囲は、プロセスの 仮想アドレス空間と呼ばれます。 各ユーザー モード プロセスには、独自のプライベート仮想アドレス空間があります。
通常、32ビットプロセスは、0x00000000から0x7FFFFFFFまでの範囲の2ギガバイトの仮想アドレス空間を持っています。
64 ビット Windows の 64 ビット プロセスでは、128 テラバイトの範囲内の仮想アドレス空間が 0x000'000000000 から 0x7FFF'FFFFFFFF) になります。
仮想アドレスの範囲は、仮想 メモリの範囲と呼ばれることもあります。 詳細については、「メモリとアドレス空間の制限」を参照してください。
次の図は、仮想アドレス空間のいくつかの主要な機能を示しています。
この図は、2 つの 64 ビット プロセス (Notepad.exe と MyApp.exe) の仮想アドレス空間を示しています。 各プロセスには、0x000'00000000 から 0x7FF'FFFFFF まで、独自の仮想アドレス空間があります。 網掛けされた各ブロックは、仮想または物理メモリの 1 ページ (4 KB のサイズ) を表します。 メモ帳プロセスでは、0x7F7'93950000 から始まる 3 つの連続した仮想アドレス ページが使用されます。 ただし、これら 3 つの連続する仮想アドレス ページは、物理メモリ内の連続しないページにマップされます。 また、どちらのプロセスも、0x7F7'939500000 から始まる仮想メモリのページを使用しますが、これらの仮想ページは物理メモリのさまざまなページにマップされます。
ユーザー領域とシステム領域
Notepad.exe や MyApp.exe などのプロセスは、ユーザー モードで実行されます。 オペレーティング システムのコア コンポーネントと多くのドライバーは、より特権の高いカーネル モードで実行されます。 プロセッサ モードの詳細については、「 ユーザー モードとカーネル モード」を参照してください。
各ユーザー モード プロセスには独自のプライベート仮想アドレス空間がありますが、カーネル モードで実行されるすべてのコードは 、システム空間と呼ばれる 1 つの仮想アドレス空間を共有します。 ユーザー モード プロセスの仮想アドレス空間は、 ユーザー空間と呼ばれます。
32 ビット Windows では、使用可能な仮想アドレス空間の合計は 2^32 バイト (4 ギガバイト) です。 通常、ユーザー空間には下位 2 ギガバイトが使用され、システム領域には上位 2 ギガバイトが使用されます。
32 ビット Windows では、ユーザー空間で 2 ギガバイトを超える容量を使用できるように (起動時に) 指定できます。 ただし、システム領域で使用できる仮想アドレスの数が少なくなります。 ユーザー領域のサイズを 3 ギガバイトまで増やすことができます。システム領域には 1 ギガバイトしか残りません。 ユーザー領域のサイズを大きくするには、 BCDEdit /set increaseuserva を使用します。
64 ビット Windows では、仮想アドレス空間の理論上の量は 2^64 バイト (16 エクサバイト) ですが、実際には 16 エクサバイト範囲のごく一部のみが使用されます。
ユーザー モードで実行されているコードは、ユーザー領域にアクセスできますが、システム領域にはアクセスできません。 この制限により、ユーザー モード コードが保護されたオペレーティング システムのデータ構造を読み取ったり変更したりできなくなります。 カーネル モードで実行されているコードは、ユーザー空間とシステム領域の両方にアクセスできます。 つまり、カーネル モードで実行されているコードは、システム空間と、現在のユーザー モード プロセスの仮想アドレス空間にアクセスできます。
カーネル モードで実行されているドライバーは、ユーザー空間のアドレスから直接読み取ったり、アドレスに書き込んだりするときに注意する必要があります。 次のシナリオは、その理由を示しています。
ユーザー モード プログラムは、デバイスからデータを読み取る要求を開始します。 プログラムは、データを受信するバッファーの開始アドレスを提供します。
カーネル モードで実行されているデバイス ドライバー ルーチンは、読み取り操作を開始し、呼び出し元に制御を返します。
その後、デバイスは現在実行中のスレッドを中断して、読み取り操作が完了したことを示します。 カーネル モード ドライバー ルーチンは、任意のプロセスに属するこの任意のスレッドの割り込みを処理します。
この時点で、ドライバーは、ユーザー モード プログラムが手順 1 で指定した開始アドレスにデータを書き込んではなりません。 このアドレスは、要求を開始したプロセスの仮想アドレス空間にあります。これは、現在のプロセスと同じではない可能性があります。
ページ プールと非ページ プール
ユーザー空間では、必要に応じて、すべての物理メモリ ページをディスク ファイルにページングできます。 システム空間では、一部の物理ページをページアウトでき、それ以外はページアウトできません。 システム領域には、メモリを動的に割り当てる領域として、ページング プールと非ページ プールの 2 つの領域があります。
ページ プールに割り当てられているメモリは、必要に応じてディスク ファイルにページアウトされる可能性があります。 非ページ プールに割り当てられているメモリは、ディスク ファイルにページアウトすることは決してできません。