仮想アドレス領域
プロセッサは、メモリの場所に対する読み取りまたは書き込みを行う際に仮想アドレスを使用します。 これらの操作中、プロセッサは、仮想アドレスを物理アドレスに変換します。
仮想アドレスを使用してメモリにアクセスする場合、いくつかの利点があります。
プログラムは、連続した範囲の仮想アドレスを使用して、物理メモリ内の大きな連続しないメモリ バッファーにアクセスできます。
プログラムは、特定の範囲の仮想アドレスを使用して、使用可能な物理メモリより大きいメモリ バッファーにアクセスできます。 物理メモリが少ない場合、メモリ マネージャーは、物理メモリのページ (通常は 4 キロバイトのサイズ) をディスク ファイルに保存します。 システムは、必要に応じて、物理メモリとディスクの間でデータまたはコードのページを移動します。
異なるプロセスで使用される仮想アドレスは分離されます。 1 つのプロセスのコードが別のプロセスまたはオペレーティング システムによって使用されている物理メモリを変更することはできません。
プロセスで使用できる仮想アドレスの範囲は、プロセスの仮想アドレス空間と呼ばれます。 個々のユーザー モード プロセスには独自のプライベート仮想アドレス領域が割り当てられます。
通常、32 ビット プロセスの仮想アドレス空間は、0x00000000 から 0x7FFFFFFF の 2 ギガバイトの範囲内にあります。
64 ビット Windows 上の 64 ビット プロセスの仮想アドレス空間は、0x000'00000000 から 0x7FFF'FFFFFFFF の 128 テラバイトの範囲内にあります。
仮想アドレスの範囲は、仮想メモリの範囲と呼ばれることもあります。 詳細については、「メモリとアドレス空間の制限」を参照してください。
次の図は、仮想アドレス空間のいくつかの主要な機能を示しています。
この図は、2 つの 64 ビット プロセス (Notepad.exe と MyApp.exe) の仮想アドレス空間を示しています。 各プロセスには、0x000'00000000 から 0x7FF'FFFFFFFF まで、独自の仮想アドレス空間があります。 網掛けされた各ブロックは、仮想メモリまたは物理メモリの 1 ページ (4 キロバイトのサイズ) を表します。 Notepad プロセスでは、0x7F7'93950000 から始まる仮想アドレスの連続する 3 ページが使用されています。 ただし、仮想アドレスのこれらの連続する 3 ページは、物理メモリ内の連続しないページにマップされています。 また、どちらのプロセスも 0x7F7'93950000 から始まる仮想メモリのページを使用していますが、これらの仮想ページは物理メモリの異なるページにマップされています。
ユーザー空間とシステム空間
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 つのデバイスから何かのデータを読み取る要求を開始します。 プログラムは、データを受信するバッファーの開始アドレスを提供します。
カーネル モードで実行されているデバイス ドライバー ルーチンが、読み取り操作を開始し、呼び出し元に制御を返します。
その後、デバイスは、現在実行中のスレッドを中断して、読み取り操作が完了したことを示します。 カーネルモード ドライバー ルーチンが、任意のプロセスに属するこの任意のスレッドの割り込みを処理します。
この時点で、ドライバーは、ユーザーモードのプログラムが手順 1 で提供した開始アドレスにデータを書き込んではなりません。 このアドレスは要求を開始したプロセスの仮想アドレス空間にあり、それは現在のプロセスと同じではない可能性があります。
ページ プールと非ページ プール
ユーザー空間では、必要に応じて、すべての物理メモリ ページをディスク ファイルにページ アウトできます。 システム空間では、ページ アウトできる物理ページとページ アウトできない物理ページがあります。 システム空間には、メモリを動的に割り当てる領域として、ページ プールと非ページ プールの 2 つの領域があります。
ページ プールに割り当てられたメモリは、必要に応じてディスク ファイルにページ アウトできます。 非ページ プールに割り当てられたメモリは、ディスク ファイルにページ アウトできません。