仮想ページ番号とオフセットを物理ページ番号とオフセットに読み替える
→ページテーブルによってアドレス変換を行う
ページテーブルでは有効かどうかというビットと仮想ページ番号に対応する物理ページを格納する
主記憶と二次記憶のやり取りはキャッシュと主記憶のやり取りに似ている
- ページフォールト
- キャッシュミスの状態
- 物理ページと対応づいていない仮想ページにアクセスする
→OSの方で強制的にページインする - ページインできない場合にはsegmentation faultになることも
- ページイン
- OSが行う
- 二次記憶から主記憶に読み込む
- ページテーブルのエントリを更新
- ページアウト
- OSが行う
- 主記憶からに次記憶に追い出す
- 追い出す物理ページは近似LRUなどで選択
- 内容が変更されていないページをページアウトするときは二次記憶上に対応する同内容のページがあれば退避不要
始めにはページテーブルには物理ページ番号か二次記憶のアドレスが入っている
有効ビットがゼロならページフォールト
→OS側の例外処理でに次記憶から読み出してページイン、ページテーブルを書き直す
二字記憶についてはライトバックを使う
ページテーブルには有効ビットの他にダーティビットも用意する
ページテーブルの置き場所は主記憶で、アドレスは物理アドレスで示す(ページテーブルのためにページテーブルが必要になる)
メモリアクセスのためにページターブルにアクセスすることになるとメモリアクセスの回数が倍になって非効率的
→一部のエントリはTLBバッファに置く(L1より早くて小さい)
TLBは並列検索気のがある連想メモリ
TLBにおけるのはエントリに物理メモリ番号が入っているもの: 有効ビットが1のものだけ
また、TLBは非常に小さくて4096エントリとか
並列検索できるからフルアソシアティブとかセットアソシアティブ
仮想ページ番号の一部をタグとして並列検索する
まずは仮想ページ番号からTLBを検索
→ヒットした
良かったね、物理ページ番号を見にいってアドレスを生成する
→ヒットしなかった
TLBミス。主記憶のページテーブルを見にいって物理ページ番号を見る
該当の仮想ページは主記憶にあるのか?
→ある
TLBミスなのでエントリをTLBに転送して格納、物理アドレスを生成する(ストールは発生する)
→ない
ページフォールト。OSの制御が始まる
ページフォールトは非常に遅いので有効ビットが0のエントリをTLB居おくのは不利
ページサイズを4kbとして、
ページテーブルですべての仮想アドレス空間をカバーしようと思ったら31bitで2MB/プロセスで大きい
48bitであればページテーブルだけで64GBになってしまう
でも、ページテーブルは高速なアクセスのためにメモリの連続領域が必要
→多段化によって対応する
多段ページテーブルでは、仮想アドレスを複数の部分に分割して索引する
例:2段構成の場合
仮想アドレス = 第1フィールド + 第2フィールド + オフセット
- ルートページテーブル(第1)は常に連続領域に確保(小さい)
- 各エントリが第2のページテーブルの先頭アドレスを指す
- 使わない仮想アドレス範囲に対応する第2ページテーブルは作らない
→必要な分だけページテーブルを確保できるのでメモリ使用量が激減する
拡張:さらに細分化すれば48bit空間でも実用的
- 9bit + 9bit + 9bit + 9bit + 12bit(offset) → 4段構成
- 各段のテーブルは512エントリ × 8B = 4KB(1ページに収まる)
- 使用していない仮想アドレス範囲の下位テーブルはページテーブルエントリに無効ビットを立てるだけで確保不要
flowchart LR subgraph VA["仮想アドレス"] direction LR F1["VPN1"] --> F2["VPN2"] --> OFF["Offset"] end F1 -->|"索引"| L1["ルート<br/>ページテーブル"] L1 -->|"第2テーブルの<br/>アドレス"| L2["第2レベル<br/>ページテーブル"] F2 -->|"索引"| L2 L2 -->|"物理ページ番号"| PPN["物理ページ番号"] PPN --> PA["物理アドレス"] OFF --> PA