仮想記憶とページング — 各プロセスに「自分だけの広い空間」を
プログラムは「アドレス0番地から連続した広大なメモリ」を前提に書かれます。でも実際のRAMは限られ、複数のプロセスで奪い合い。この矛盾を解くのが仮想記憶。仮想アドレスをページテーブルで物理アドレスに翻訳し、足りなければディスクに退避する — その変換の一部始終をアニメで追います。
1. アドレスは(ページ番号 + オフセット)に割れる
仮想記憶では、アドレス空間をページという固定サイズの区画に分けます。すると、どんな仮想アドレスも上位ビット=ページ番号、下位ビット=ページ内オフセットにきれいに分解できます。ページサイズが 2k なら、下位 k ビットがそのままオフセットです。
下でアドレスとページサイズを動かして、ビットがどこで区切られるか見てください。
仮想アドレスの分解 — 上位=ページ番号 / 下位=オフセット
8ビットの仮想アドレスを例に。青=ページ番号(上位ビット)、緑=オフセット(下位ビット)。オフセットのビット数を増やすとページが大きくなり(ページサイズ = 2ビット数)、ページの数は減ります。区切り線が左右に動くのが分解の本質です。
仮想アドレス = ページ番号 × ページサイズ + オフセット
オフセットは変換で変わらない。翻訳されるのは「ページ番号 → フレーム番号」の部分だけ。
2. 仮想 → 物理 の翻訳(ページテーブル)
プロセスから見た仮想ページは連続していますが、対応する物理メモリのフレームはバラバラの場所に散らばっていて構いません。この対応表がページテーブル。CPUはアクセスのたびに、ページ番号を鍵にテーブルを引き、フレーム番号を得て、オフセットを足して物理アドレスを組み立てます。
アドレス変換の流れ — 連続した仮想が、散らばった物理へ
左=仮想アドレス空間(連続したページ)、中=ページテーブル、右=物理メモリ(散らばったフレーム)。光る点がアクセスの流れ:仮想ページ → テーブル参照 → 物理フレーム。左では隣どうしのページが、右ではてんでバラバラの位置に写像されているのが分かります。だからメモリの断片化を気にせず「連続した広い空間」に見せられるのです。
POINT — なぜ「表」で間接参照するのか
ページテーブルという1枚の翻訳表をはさむだけで、連続の錯覚(プログラムには連続に見える)、断片の活用(物理はバラバラでOK)、隔離(プロセスごとに別の表)、退避(一部をディスクへ)が同時に手に入る。仮想記憶は「間接参照は万能」の見事な実例。
物理アドレス = フレーム番号 × ページサイズ + オフセット
オフセットはそのまま持ち越す。変換されるのは前半(ページ番号→フレーム番号)だけ。
3. ページフォールトとTLB — 無ければディスクから運ぶ
RAMは有限なので、全ページを載せておけません。テーブルを引いて「まだRAMに無い」と分かるとページフォールトが起き、OSがディスクから該当ページを読み込みます。空きが無ければ、どれかを追い出して(置換/LRU)場所を空けます。さらに、毎回テーブルを引くのは遅いので、直近の変換結果をTLBという小さなキャッシュに覚えておきます。
アクセス列をたどる — TLBヒット / テーブル参照 / ページフォールト
アクセスのたびに3段階で探します:まずTLB(最速・緑)→ 無ければページテーブル(RAM内・橙)→ それでも無ければページフォールト(赤/ディスクから読み込み、RAMが満杯なら1ページ追い出し)。同じページを続けて触るとTLBに当たり、初めてのページはフォールトになります。右下の数字でフォールト回数・TLBヒット率の変化を追ってください。
注意 — スラッシング
作業に必要なページ集合(ワーキングセット)がRAMに収まらないと、追い出したページをすぐまた読み込む…を繰り返し、ディスクI/Oばかりで計算が進まない状態=スラッシングに陥る。ディスクはRAMより桁違いに遅い(数万〜数十万倍)ので、フォールト1回の代償は大きい。TLBヒット率とフォールト率が、体感速度を大きく左右する。
4. プロセスの隔離 — 同じ仮想アドレスが別の物理を指す
仮想記憶の最大の恩恵の一つが隔離(保護)です。プロセスごとに別のページテーブルを持たせれば、AとBがまったく同じ仮想アドレスを使っても、翻訳先の物理フレームは別。だから互いのメモリを覗くことも壊すこともできません。逆に、意図的に同じフレームを指させれば共有メモリになります。
2つのプロセス — 同じ仮想番地、違う物理フレーム
左=プロセスA、右=プロセスB、中央=物理メモリ。両者が同じ仮想ページ番号にアクセスしても、それぞれのページテーブルが別の物理フレームへ導くので衝突しません(隔離)。チェックを入れると同じフレームを指すようになり、これが共有ライブラリやプロセス間通信の土台になります。
5. まとめ — 1枚の翻訳表がすべてを解く
- ページ/フレーム:仮想も物理も固定長の区画に分割。アドレスは(番号+オフセット)に割れる。
- ページテーブル:仮想ページ→物理フレームの対応表。連続の錯覚・断片活用・隔離・退避を同時に実現。
- ページフォールト/TLB:RAMに無ければディスクから運び、必要なら置換。TLBで変換を高速化。
- 隔離と共有:別テーブル=プロセス隔離、同フレーム=共有メモリ。
一歩先へ — 多段ページテーブルと巨大アドレス空間
64ビット空間ではページテーブルを1枚のフラットな配列にすると天文学的サイズになる。そこで実機は多段(階層)ページテーブル(x86-64は4〜5段)を使い、使っている部分だけ表を作る。加えてヒュージページでTLBの守備範囲を広げ、Copy-on-Writeでforkを高速化し、メモリマップトファイルでファイルをそのままアドレス空間に貼り付ける。すべては「仮想と物理の間に翻訳表をはさむ」という、このレッスンの一手から派生している。