仮想メモリとは何か
仮想メモリとは、プロセスごとに「自分専用の、大きくて連続したメモリ」があるように見せる、OSとプロセッサのしくみです。プロセスどうしがデータを壊し合わず、物理メモリより大きな仕事も動かせます。
マンションの部屋番号を考えてください。どの棟にも101号室があります。ただし、101号室が指す本物の部屋は、棟ごとに違います。仮想アドレスも同じ使われ方をします。
このレッスンのゴール
メモ
ページテーブルを使って、仮想アドレスを物理アドレスに直すことができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| 仮想アドレス | プロセスが使う、見せかけの番地 | |
| 物理アドレス | 本物のメモリの番地 | |
| ページ | 仮想アドレスの側の、同じ大きさの区切り | |
| フレーム | 物理メモリの側の、同じ大きさの区切り | |
| ページテーブル | ページ番号からフレーム番号を引く表 | |
| オフセット | ページの中での位置 | 57 |
学生が入力するセルは、このプレビューでは空白です。
メモリは同じ大きさに区切る
OSは、仮想アドレスの世界を、同じ大きさのページに区切ります。物理メモリも、同じ大きさのフレームに区切ります。1ページが1フレームに入ります。
ページの大きさは、多くのPCで4096バイトです。次のコマンドで、この機械の大きさを調べられます。
ページの大きさを出す
getconf PAGESIZEここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
仮想アドレスはページ番号とオフセットに分かれる
仮想アドレスを、ページの大きさで割ります。商がページ番号で、余りがオフセットです。オフセットは、そのページの先頭から何バイト目かを表します。
例として、アドレス12345を4096で割ります。商は3、余りは57です。つまり、ページ3の57バイト目です。
商と余りを計算する
python3 -c "print(12345 // 4096, 12345 % 4096)"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ページテーブルでフレームを探す
プロセスごとに、OSはページテーブルを1つ持ちます。ページ番号から、入っているフレーム番号を引く表です。
物理アドレスは、フレーム番号にページの大きさをかけて、オフセットを足したものです。ここからは、計算しやすいように、1ページを100バイトとします。
例: 4ページのページテーブル
| ページ番号 | フレーム番号 | 意味 |
|---|---|---|
| 0 | 5 | フレーム5に入っている |
| 1 | 2 | フレーム2に入っている |
| 2 | -1 | 今はメモリにない |
| 3 | 7 | フレーム7に入っている |
学生が入力するセルは、このプレビューでは空白です。
例: 仮想アドレスを直す
| 仮想アドレス | ページ番号とオフセット | フレーム | 物理アドレス |
|---|---|---|---|
| 20 | 0 と 20 | 5 | 5×100+20 で 520 |
| 150 | 1 と 50 | 2 | 2×100+50 で 250 |
| 399 | 3 と 99 | 7 | 7×100+99 で 799 |
| 250 | 2 と 50 | なし | ページフォールト |
学生が入力するセルは、このプレビューでは空白です。
1つのアドレスを直してみる
page_size = 100
page_table = [5, 2, -1, 7]
address = 150 # 399 などに変えてみましょう
page = address // page_size
offset = address % page_size
frame = page_table[page]
print(frame * page_size + offset)
Linuxで本物の数を見る
Linux は、物理メモリの量を /proc/meminfo に出します。全体が MemTotal、空きが MemFree です。
プロセスごとの情報は /proc/自分/status にあります。VmSize は仮想アドレスの大きさで、VmRSS は今フレームに入っている分です。数は機械ごとに違うので、次のコマンドは項目名だけを取り出します。
物理メモリの項目名
grep -E '^(MemTotal|MemFree)' /proc/meminfo | cut -d: -f1ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
仮想の大きさと実際の分の項目名
grep -E '^(VmSize|VmRSS)' /proc/self/status | cut -d: -f1ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ページフォールトはOSに助けを求める
ページテーブルに「メモリにない」とあるページを使うと、ページフォールトが起きます。プロセッサがOSを呼び、OSがディスクからそのページを空きフレームに読み込みます。
読み込みが終われば、ページテーブルを直して、同じ命令をやり直します。プログラムは、何も気づきません。
よくある間違い
注意
「仮想アドレスは、物理アドレスと同じ場所を指す」と考える人が多くいます。仮想アドレスは、ページテーブルを通して初めて場所が決まります。別のプロセスの同じ仮想アドレスは、別のフレームを指すのがふつうです。
例: 同じページ0が別のフレームへ
| プロセス | 仮想アドレス | ページ0のフレーム | 物理アドレス |
|---|---|---|---|
| A | 30 | 5 | 530 |
| B | 30 | 9 | 930 |
学生が入力するセルは、このプレビューでは空白です。