メモリ仮想化とは — 仮想アドレス・ページング・TLBからハイパーバイザ最適化と運用対策まで

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

「メモリ仮想化(virtual memory)」は、実際の物理メモリ(RAM)とプログラムが扱うアドレス空間を切り離し、プログラムには連続した大きなアドレス空間を与えつつ、実際には分割・再配置して管理する仕組みです。これによりプロセス間の独立性・保護、多数のプロセスの同時実行、限られた物理メモリの有効活用が可能になります。文脈によっては、ハイパーバイザが複数のゲストOSのメモリを仮想化する「ハイパーバイザレベルのメモリ仮想化」も含めて用いられます。本コラムではOSレベルの仮想メモリの基本から、仮想化環境特有の機構、性能や運用上の注意点まで広く深掘りして解説します。

基本概念:仮想アドレスと物理アドレス、MMU

  • 仮想アドレス空間:各プロセスに与えられる論理的なアドレス空間。プロセスはこの空間を自由に使えるため、他のプロセスの領域を意識する必要がありません。
  • 物理アドレス:実際に存在するRAM上の住所。
  • MMU(メモリ管理ユニット):CPUと連携して、仮想アドレスを物理アドレスに変換するハードウェア。ページテーブルのエントリや保護ビット(読み書き/実行、ユーザ/カーネル)を参照します。
  • TLB(Translation Lookaside Buffer):最近参照した仮想→物理変換をキャッシュする小容量の高速メモリ。TLBミスは性能に大きく影響します。

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

今日の一般的なOSは「ページング」を採用します。メモリは固定長のページ(典型的には4KiB)に分割され、ページ単位で仮想と物理を対応付けます。ページテーブルは複数レベル(例:x86-64の4〜5レベル)で構成され、巨大なアドレス空間を効率的に管理します。

一方、セグメンテーションは可変長の区間で管理する方式で、古い設計や一部用途で使われますが、現代の主流はページングです。

ページフォルト、スワップ、ページ置換

  • ページフォルト:プロセスがアクセスした仮想ページが物理メモリ上にない場合に発生します。OSはディスクから該当ページを読み込む、または割当てを行い、処理を再開します。
  • スワップ(スワッピング):物理メモリが不足したとき、使用頻度の低いページをディスクのスワップ領域に書き出してメモリを確保します。スワップの発生は遅延(ディスクI/O)を伴い性能劣化を招きます。
  • ページ置換アルゴリズム:どのページを追い出すかを決める。理想はLRU(最近使われていないものを追い出す)だが実装上は近似(CLOCK、Second Chanceなど)が多いです。

仮想化環境におけるメモリ仮想化(ハイパーバイザ)

仮想マシン(VM)を動かすハイパーバイザは、ゲストOSが見ている「ゲスト物理アドレス」をさらにホストの「実物理アドレス」に変換する必要があります。これを実現するためにSLAT(Second Level Address Translation)という仕組みがあり、代表例はIntelのEPT(Extended Page Tables)やAMDのNPT(Nested Page Tables)です。

加えて、ハイパーバイザは以下のような技術で物理メモリを効率化します:

  • バルーニング(Ballooning):ゲスト内のドライバ(balloon driver)を使ってゲストからメモリを強制解放させ、ホストがその分を他に割り当てる。
  • KSM(Kernel Samepage Merging)等の重複排除:複数ゲストで同一内容のページを一つにまとめることでメモリ容量を節約。
  • メモリオーバーコミット:ホストがゲスト合計より少ない物理メモリで多数のゲストを動かす運用。便利だがスワップやパフォーマンス劣化のリスクがある。

性能考慮:TLB、ページサイズ、巨大ページ

仮想化の性能はTLBミスや二重のアドレス変換のコストに敏感です。これを改善する技術が「Huge Pages(巨大ページ)」で、一般的には4KiBの代わりに2MiBや1GiBなど大きなページを使うことでページ表の深さを浅くしTLBヒット率を上げます。LinuxではTransparent Huge Pages(THP)や手動で設定するHugeTLBがあります。

メモリ仮想化とセキュリティ

  • メモリ分離と保護:仮想メモリはプロセス間の分離をハードウェアレベルで実現し、不正アクセスを防ぎます。
  • ASLR(Address Space Layout Randomization):仮想アドレスをランダム化して攻撃を難しくする手法。仮想メモリの存在がASLRを可能にしています。
  • サイドチャネルや投機実行脆弱性:Meltdown/ Spectreなど、仮想化やメモリ階層を突く攻撃が報告されており、ハードウェアおよびOSの対策が必要です。

運用上の注意点とトラブルシューティング

  • スワップの多発はI/O負荷とレイテンシを増大させるため、まずはワークロードのメモリ使用を見直す。必要であれば物理メモリ増設、またはメモリリークの検出。
  • メモリオーバーコミット環境では過度なオーバーコミットがスラッシング(頻繁なページイン/アウト)を引き起こす。ホスト側で監視とアラートを設定する。
  • 巨大ページを安易に有効化するとメモリ断片化や一部ワークロードで逆に悪化する場合があるため、検証が必要。
  • 仮想環境ではバルーニングやKSMの使用が有効だが、KSMはCPU負荷を伴うことがある。

実用例と適用場面

  • デスクトップやサーバーOSでのプロセス分離と仮想アドレス提供(ほとんど全ての一般OS)
  • 大規模仮想化環境での効率化(クラウドプロバイダ、データセンター)
  • コンテナとVMの違い:コンテナはホストカーネルのメモリ管理を共有するため「仮想メモリの仮想化」は行わないが、カーネルが提供する名前空間やcgroupで割当管理する。
  • 組込みやリアルタイム環境では、ページフォルトが許容できない場合があり仮想メモリを限定的にしか使わない設計もある。

まとめ

メモリ仮想化(virtual memory)は、現代のOSと仮想化基盤の中核的な技術であり、プログラムの簡潔さ・安全性・効率性を大幅に高めます。同時に、TLBミスやスワップによる性能低下、仮想化特有の二重翻訳コストなどの課題も存在します。設計や運用では、ページサイズや巨大ページの活用、メモリオーバーコミットの程度、バルーニングやKSMの採用可否などをワークロードに合わせて慎重に選ぶことが重要です。

参考文献