仮想メモリ完全ガイド:ページング・TLB・スワップからLinux/Windowsの実践チューニングまで

はじめに — 仮想メモリとは何か

仮想メモリ管理とは、物理メモリ(RAM)の制約を抽象化し、プロセスに対して連続した大きなアドレス空間を提供するOSの仕組みです。プロセスは「仮想アドレス」を扱い、OSとハードウェア(MMU: Memory Management Unit)がそれを「物理アドレス」に対応づけます。これにより、メモリ保護、プロセス間のアドレス空間分離、メモリの効率的利用(スワップ・ページング)、共有メモリやメモリマッピングといった機能が実現します。

基本概念

  • 仮想アドレス空間: 各プロセスに与えられるアドレスの集合。連続しているように見えるが、物理メモリ上の配置は断片化され得る。
  • ページ(page): 仮想→物理変換と管理の単位。多くのシステムで4KiBが基本だが、2MiB/1GiBなどの大ページ(hugepage)もある。
  • ページテーブル: 仮想ページと物理フレームの対応関係を保持するデータ構造。OSとCPUが協調して管理する。
  • TLB(Translation Lookaside Buffer): 最近使われた仮想→物理変換をキャッシュする高速メモリ。TLBミスは性能上の重要な要因。
  • ページフォールト: 仮想ページが物理メモリに割り当てられていない場合に発生。OSが割り当てやスワップ入れを行う。

ページングとセグメンテーション

仮想メモリの実装法として代表的なのがページングとセグメンテーションです。ページングは固定長のページ単位で管理し、外部断片化を防ぎます。セグメンテーションは論理的な区分(コード・データ・スタック等)を可変長で管理し、プログラマ視点での扱いやすさを提供します。多くの現代的OSはページングを基盤とし、必要に応じてセグメント的機能(例:x86のリング保護や分離)を併用します。

ページテーブルの種類と実装

ページテーブルは構造やスケーラビリティの観点で複数の方式があります。

  • 階層型ページテーブル(multi-level): 大きな仮想空間を小さなテーブルの階層で表現する。x86-64では4レベル(あるいは5レベル)構成が一般的。
  • 反転(inverted)ページテーブル: 物理フレームをインデックスにして仮想ページ情報を持つ。大規模アドレス空間でメモリ使用を節約する目的で用いられることがある(例: 一部のUNIX実装)。
  • ハッシュ方式: 仮想ページをハッシュで管理するアーキテクチャも存在(例: 一部の32/64ビットアーキテクチャ)。

TLB とページウォーク

TLBは仮想→物理変換の遅延を避けるために不可欠です。TLBミス時、ハードウェア(x86など)なら自動でページテーブルをウォークしてPTE(Page Table Entry)を参照します。ハードウェアで自動化されないアーキテクチャでは、OSがソフトウェアでTLBリロードを行います。ページテーブル構造はTLBヒット率に大きく影響し、階層が深いほどウォークコストが増える可能性があります。

ディマンドページングとページフォールト処理

多くのOSは「ディマンドページング」を採用し、実際にアクセスされたページのみを物理メモリに読み込みます。ページフォールト発生時の典型的な処理は以下の通りです。

  • プロセスの権限とアクセス違反の判定(保護違反ならシグナルや例外)
  • 対象ページがスワップ領域にあればディスクから読み込み、なければ新しいフレームを割り当て初期化
  • ページテーブルとTLBの更新
  • プロセスの再開

この処理はディスクI/Oを伴うため遅く、ページフォールトの頻発は性能劣化(スラッシング)を引き起こします。

ページ置換アルゴリズム

物理メモリが不足した際にどのページを追い出すかを決めるアルゴリズムは重要です。代表的なもの:

  • FIFO: 最も古く入ったページを追い出す。実装は容易だが性能は保証されない。
  • LRU(Least Recently Used): 最近使われていないページを追い出す。理想的だが厳密なLRUは実装コストが高い。
  • Clock(Second Chance): 擬似LRUで広く使われる。参照ビットを用いる。
  • Optimal(Belady): 将来の参照を完璧に知っていれば最適。実運用では不可。
  • NFU, Aging: 統計情報を用いた近似LRU。

スワップ、スワップアウトとスラッシング

物理メモリ不足時に、ページをディスク上のスワップ領域に書き出す(スワップアウト)ことでメモリを確保します。スワップは容量を増やすが、アクセス遅延は大きいため多用は逆効果です。頻繁にページングが発生するとスラッシング(システム全体の性能低下)を招きます。Linuxではswappinessなどのパラメータで振る舞いを調整できます。

コピーオンライト(COW)と共有メモリ

fork()時に親子プロセスでメモリコピーを遅延するためCOWが使われます。読み取りは共有で行い、書き込みが発生した段階で実際のコピーを作ることで効率化します。メモリマップ(mmap)によるファイル共有や匿名共有、プロセス間共有も仮想メモリの重要な利用法です。

大ページ(HugePages)とパフォーマンスチューニング

ページサイズを大きくすることでTLBエントリあたりのカバー範囲が広がり、TLBミス削減・TLBウォーク低減により性能向上が期待できます。x86-64では通常4KiB、2MiB(huge)、1GiB(gigantic)など。LinuxではTransparent HugePages(THP)やhugetlbfs、madviseでの制御が可能です。

仮想化との関係(ハイパーバイザ)

仮想化環境ではゲストOSの仮想→物理変換に加え、ホスト実機の物理変換が必要になります。これを高速化するためにIntel EPTやAMD NPTといったネストされたページテーブル(EPT/NPT)や、ハードウェア支援によるTLB拡張が使われます。さらにメモリオーバーコミットやバルーニング(ballooning)、KSM(Kernel Samepage Merging)などの技術でホスト側のメモリ配分を動的に調整します。

安全性と保護機能

仮想メモリはASLR(Address Space Layout Randomization)などセキュリティ機能の基盤です。アクセス権(読み・書き・実行)をページ単位で設定でき、不正アクセスがあれば例外を発生させ隔離します。一方で、Rowhammerのようなハードウェア脆弱性やスワップ中のデータ管理の問題(スワップ内容の暗号化)など、仮想メモリ固有のセキュリティ課題もあります。

実装の現実(Linux/Windows の例)

  • Linux: ページキャッシュ、ページキャ種別、ページフレーム管理、4/2MiB/1GiBページ、swappiness、OOM Killer、KSM、THP など豊富な機能とチューニングパラメータ。
  • Windows: 仮想アドレス空間、ページファイル(pagefile.sys)、AWE(Address Windowing Extensions)、Large Pages、メモリ優先度やメモリ圧縮(近年のバージョンで導入)など。

診断とツール

Linuxでの調査例:

  • free, vmstat, top/htop — メモリ使用状況
  • /proc//maps, /proc//smaps — プロセスの仮想メモリマップ
  • pmap — プロセスのメモリマップ表示
  • perf, sar — 性能カウンタやスワップ・ページフォールトの解析

まとめ — 設計上のトレードオフ

仮想メモリ管理は性能、保護、機能性のバランスを取る設計です。ページサイズや置換アルゴリズム、スワップ戦略、TLB管理などの選択はワークロードによって最適解が変わります。近年は大メモリ・多数コア・仮想化環境・セキュリティ要件の変化に伴い、透明巨大ページ、KSM、メモリ圧縮、ネストページングといった新しい要素が重要になっています。実運用ではOS固有の実装とチューニング項目を理解し、適切に調整することが求められます。

参考文献