仮想記憶(ページング)
各プロセスに“自分専用の広いメモリ”があるかのように見せる仕組み。アドレスを翻訳し、足りなければディスクへ逃がして、物理メモリ以上に使えるようにする。
- 1.仮想記憶は、プロセスが使う 仮想アドレス を MMU が 物理アドレス に翻訳する仕組み。プロセスごとに独立した広大なメモリ空間を見せる。
- 2.メモリは ページ(固定長ブロック)単位で管理し、ページテーブル で対応づける。物理に無いページは ページフォルト で読み込む。
- 3.メリットは プロセス分離(互いのメモリを壊せない)と 物理より大きく見せられる こと。翻訳の高速化に TLB を使う。
なぜ仮想化するのか
もし全プロセスが物理メモリの番地を直接触っていたら、こうなります。
- あるプロセスのバグが、別プロセスや OS のメモリを 壊せてしまう
- プログラムを書く側が「自分がどの番地に置かれるか」を 毎回気にしないといけない
- 搭載メモリより大きいデータは そもそも扱えない
仮想記憶はこれらをまとめて解決します。各プロセスには 0 番地から始まる連続した広大な仮想アドレス空間(64bit なら理論上 16EB 規模)が与えられ、実際の物理配置は OS と MMU が裏で面倒を見ます。
プロセス A の仮想アドレス 0x4000 と、プロセス B の 0x4000 は まったく別の物理メモリ を指します(共有メモリなど明示的な例外を除く)。だから「同じアドレス」でもぶつかりません。これがプロセス分離の正体です。
仕組み:ページとページテーブル
仮想記憶は、メモリを ページ と呼ぶ 固定長のブロック(典型的には 4KB)に区切って管理します。物理側の同じ大きさの枠を ページフレーム と呼びます。
「どの仮想ページが、どの物理フレームに置かれているか」の対応表が ページテーブル です。アドレス翻訳はこう進みます。
仮想アドレス = [ ページ番号 | ページ内オフセット ]
│
▼ ページテーブルを引く(MMUが実行)
物理フレーム番号
│
▼
物理アドレス = [ フレーム番号 | ページ内オフセット ]
オフセット(ページ内の位置)はそのまま使い、上位のページ番号だけを翻訳 します。実際の OS では、ページテーブルは数百万エントリにもなるため、多段(マルチレベル)ページテーブル で必要な部分だけを持つのが普通です。
翻訳表は各プロセス専用です。OS はコンテキストスイッチのたびに「今どのページテーブルを使うか」を切り替えます(x86 なら CR3 レジスタの差し替え)。これにより、同じ仮想アドレスがプロセスごとに別の物理を指せます。
MMU と TLB:翻訳を速くする
アドレス翻訳は メモリアクセスのたびに毎回 発生します。これを CPU 内蔵の MMU(Memory Management Unit) がハードウェアで行います。
ただし、翻訳のためにメモリ上のページテーブルを引くと、それ自体がメモリアクセスになり遅くなります。そこで MMU は、最近使った翻訳結果を TLB(Translation Lookaside Buffer) という小さなキャッシュに保持します。
- TLB ヒット:表を引かずに即座に物理アドレスが分かる(高速)
- TLB ミス:ページテーブルを実際に辿って翻訳し、結果を TLB に入れる
CPU のデータキャッシュ(L1/L2…)が「中身(データ)」をキャッシュするのに対し、TLB は「アドレスの対応づけ」をキャッシュします。役割が違うので混同しないこと。
スワップとページフォルト:物理より大きく見せる
物理メモリに乗り切らないページは、OS が ディスク上の領域(スワップ領域 / ページファイル) に退避します。これにより「物理メモリより大きく見せる」が実現します。
プロセスが 物理メモリ上に存在しないページ に触ると、MMU は ページフォルト という例外を発生させ、OS に処理を委ねます。
1. プロセスがページ X にアクセス
2. ページテーブルに「物理に無い」フラグ → ページフォルト発生
3. OS が割り込んで、必要なら空きフレームを確保
(空きが無ければ既存ページを1つ追い出す=ページ置換)
4. ディスクからページ X を読み込む
5. ページテーブルを更新し、止めた命令を再実行 → 何事もなく続行
追い出すページの選び方を ページ置換アルゴリズム と呼び、LRU(最近最も使われていないものを優先)などが基本です。スワップ先がディスクのため、ここが頻発すると一気に遅くなります。
物理メモリが足りず、「追い出した直後にまた要る」を繰り返す状態を スラッシング(thrashing) と呼びます。CPU が処理ではなくページの出し入れに忙殺され、システム全体が激しく遅くなります。対策は実メモリの増設や、同時に動かす量を減らすこと。
名前に fault と付きますが、ページフォルトは 正常な仕組みの一部 です。スワップからの読み戻しのほか、まだ割り当てていないメモリへの初回アクセス(デマンドページング)でも起きます。一方、どの仮想ページにも対応しない不正な番地に触ると セグメンテーション違反 となり、こちらはプログラムが落ちます。
用語の対比
仮想記憶まわりは「対になる概念」を押さえると整理できます。
| 観点 | 仮想アドレス(論理) | 物理アドレス(実体) |
|---|---|---|
| 誰が見る | プロセス/プログラム | メモリチップ(ハードウェア) |
| 範囲 | プロセスごとに広大・独立 | 搭載メモリ分だけ・全体で共有 |
| 単位 | ページ(例: 4KB) | ページフレーム(同サイズ) |
| 翻訳役 | — (翻訳される側) | MMU+ページテーブルで決まる |
| 足りない時 | スワップで物理外へ退避可能 | 増設しない限り増えない |
つまずきポイント
- 「仮想メモリ=スワップ(ページファイル)」ではない。スワップは仮想記憶の一機能にすぎません。仮想記憶の本体は「アドレス翻訳によるプロセス分離」です。スワップを無効化しても仮想記憶は動いています。
- 物理メモリが余っていてもページフォルトは起きる。初回アクセス時に実フレームを割り当てる遅延確保(デマンドページング)があるためです。
- ページが大きいほど常に良い、わけではない。大きいページ(ヒュージページ)は TLB の効率を上げますが、使わない部分まで確保してしまう内部断片化が増えます。
まとめ
- 仮想記憶は 仮想アドレスを物理アドレスに翻訳 する仕組みで、ページ単位 で管理し ページテーブル で対応づける。
- 翻訳は MMU がハードウェアで実行し、TLB でキャッシュして高速化する。
- 物理に無いページは ページフォルト を契機に スワップ から読み込み、物理より大きく見せる。
- 最大の狙いは プロセス分離(互いのメモリを壊せない)と 大きく見せること の両立。
関連して、確保・解放の方針そのものは メモリ管理、複数プロセスの切り替えは プロセスとスレッド も合わせて読むと理解が深まります。
OS Article
仮想記憶(ページング)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
仮想記憶
比較で見る軸
難易度: intermediate / カテゴリ: OS / タグ数: 4
導入後に効く点
メモリは ページ(固定長ブロック)単位で管理し、ページテーブル で対応づける。物理に無いページは ページフォルト で読み込む。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- intermediate
- カテゴリ
- OS
- タグ数
- 4
判断チェックリスト
- 自社の用途が「仮想記憶 / ページング」に近いか確認する。
- 強みである「仮想記憶は、プロセスが使う 仮想アドレス を MMU が 物理アドレス に翻訳する仕組み。プロセスごとに独立した広大なメモリ空間を見せる。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。