ページテーブルとは — 仮想メモリの仕組み・PTEとTLBの役割、x86‑64多段階実装を徹底解説

ページテーブルとは

ページテーブル(page table)は、仮想メモリを用いるコンピュータシステムにおいて「仮想アドレス」を「物理アドレス」に変換するためのデータ構造です。各プロセスは自分専用の仮想アドレス空間を持ち、プログラムは仮想アドレスを参照してメモリにアクセスします。ページテーブルはその仮想アドレスと物理メモリ上のフレーム(ページフレーム)との対応関係を保持し、CPUまたはMMU(メモリ管理ユニット)がアドレス変換を行う際に参照されます。

基本原理

仮想アドレスは通常「ページ番号」と「ページ内オフセット」に分割されます。ページサイズ(例:4KiB)が固定されていると、下位ビットがページ内オフセットを示し、上位ビットがページ番号になります。ページテーブルはページ番号をインデックスとして参照し、対応するページテーブルエントリ(PTE: Page Table Entry)から物理フレーム番号を得ます。フレーム番号とページ内オフセットを組み合わせることで最終的な物理アドレスが得られます。

アドレス変換の流れ(簡略)

  • CPUが仮想アドレスを生成する。
  • MMUがページ番号を基にページテーブルを参照し、PTEを取得する。
  • PTEが示す物理フレーム番号とオフセットを結合して物理アドレスを生成する。
  • PTEに「present(在処)ビット」がクリアされている場合、ページフォールトが発生し、OSがディスク(スワップ領域)やファイルからページをロードする。

ページテーブルの主な種類

ページテーブルの実装はアーキテクチャやOSによって異なります。代表的な方式を以下に示します。

  • 単純(線形)ページテーブル:仮想ページ番号ごとに1つのエントリを持つ配列。実装は単純だが、仮想アドレス空間が広いと巨大になりメモリ効率が悪い。
  • 多段階(マルチレベル)ページテーブル:ページテーブルをツリー構造にして、アクセスされる領域のみ下位テーブルを割り当てる方式。x86-64では4レベル(PML4→PDPT→PD→PT)が一般的で、大きな仮想空間でもメモリ使用を抑えられる。
  • 反転ページテーブル(Inverted Page Table):物理フレームをインデックスに取り、そこから対応する仮想ページとプロセス情報を保持する方式。プロセス数が多く仮想空間が大きい場合に有利だが、検索にハッシュ等を用いる必要があり実装が複雑。
  • ハッシュページテーブル:仮想アドレスをハッシュしてエントリを探す方式。PowerPCなど一部アーキテクチャで使われることがある。

ページテーブルエントリ(PTE)の主なフィールド

PTEにはアーキテクチャ依存の複数のビットとフレーム番号が含まれます。一般的なフィールドは次の通りです。

  • フレーム番号(物理フレームのベースアドレス)
  • present(在処)ビット:ページが物理メモリ上にあるか
  • 読み書き(R/W)ビット:書き込み許可(保護)
  • ユーザ/スーパーバイザ(U/S)ビット:ユーザ空間からアクセス可能か
  • アクセス(accessed / referenced)ビット:参照されたかのフラグ(ページ置換で利用)
  • ダーティ(dirty)ビット:ページが書き込みされたか(スワップ時の書き戻し判断)
  • キャッシュ制御ビット(PWT, PCDなど):キャッシュの挙動制御
  • グローバル(global)ビット:コンテキスト切替でTLBから保持させるか等の制御
  • NX(No Execute)ビット:実行不可(実行保護)— 近年のCPUで一般的

これらのビットの名称や存在はアーキテクチャ(x86, ARM, RISC-V等)によって異なります。例えばx86-64のPTEにはNXビットやPAT関連のビットがあり、4KiB/2MiB/1GiBのページサイズをサポートします(詳細は各アーキテクチャの仕様書参照)。

TLB(Translation Lookaside Buffer)と性能

ページテーブル参照を毎回メモリから行うと非常に遅いため、CPUはTLBという高速キャッシュを持ち、最近参照した仮想ページ→物理フレームの対応をキャッシュします。TLBミスが発生するとMMUはページテーブルを参照(場合によっては多段階を辿る)し、TLBにエントリをロードします。TLBのヒット率はメモリアクセス性能に直結するため、TLBを効率よく使うための工夫(局所性、巨大ページの利用、ページ配置の最適化など)が重要です。

OSによるページテーブル管理とページフォールト

ページテーブルはOSが生成・管理します。新しいプロセスの作成時にページテーブルのトップレベル構造が割り当てられ、プロセスの実行・終了・コンテキストスイッチ時に適切に扱われます。ページがメモリ上にない場合(presentビットが0)にアクセスが起こるとページフォールトが発生し、OSのフォールトハンドラが介入して以下のような処理を行います。

  • アクセス違反(許可なしのアクセス)ならシグナル(例:SIGSEGV)や例外を返す。
  • ページがスワップアウトされていればディスクからロードし、PTEを更新する。
  • ファイルマッピングのページであれば該当ファイルブロックを読み込む。
  • 需要ページングやCopy-on-Write(COW)のため、子プロセスとの分離やPTEの共有・コピーを行う。

実装上の工夫と課題

ページテーブル運用には性能・スケーラビリティ上の課題が多く、OSやハードウェアでさまざまな工夫がなされています。

  • 巨大ページ(Huge/TLB large pages): 4KiBより大きなページ(例:2MiB, 1GiB)を使うことでTLBの有効範囲を広げ、TLBミスを減らす。
  • Copy-on-Write(COW): fork時にページを複製しないで共有し、書き込みが起きたときに初めてコピーすることでメモリ効率を向上。
  • ASLR(Address Space Layout Randomization): セキュリティ対策のために仮想空間の配置をランダム化する。ページテーブルの初期化や管理に影響。
  • TLB shootdown(TLB一斉無効化): マルチプロセッサ環境でページテーブルを変更した際、他のCPUのTLBエントリを無効化する必要があり、コストとなる。
  • NUMA最適化やページ配置アルゴリズム:メモリの物理配置が性能に影響するため、ページ割り当てルールの工夫が必要。

実例:x86-64の多段階ページテーブル(概要)

x86-64では通常4レベル(PML4, PDPT, PD, PT)のページテーブルを用います。仮想アドレスはこれらのレベルのインデックスに分割され、最下位のPTエントリが最終的なフレーム番号を指します。なお、x86-64は4KiB(標準)、2MiB(大ページ)、1GiB(超大ページ)をサポートします(CPU機能とOSのサポートが必要)。PTEには present, R/W, U/S, PWT, PCD, accessed, dirty, PAT, global, NX 等のビットが含まれます(仕様はIntel/AMDのマニュアル参照)。

まとめ

ページテーブルは仮想メモリと物理メモリをつなぐ重要な仕組みで、アドレス変換、保護、ページ管理(スワップ、COW、共有)、性能(TLBとの連携)と密接に関わります。実装には多段階テーブル、反転テーブル、ハッシュテーブルなどの手法があり、各方式はトレードオフ(メモリ効率、検索コスト、実装複雑性)を持ちます。実務ではCPUアーキテクチャ仕様やOSの実装を正確に参照し、用途に合わせたページサイズやメモリ管理戦略を選ぶことが重要です。

参考文献