この章では,メモリ管理の応用であり,かつ,あたり前となった仮想記憶(virtual memory) について説明する.最近の CPU には,ハードウエアとして仮想記憶をサポートするものが多い. 仮想記憶をサポートするハードウエアを MMU(Memory Management Unit) という.
主記憶というメモリは,「番地」(アドレス,address)とよぶ番号でその位置を識別する ことができた.そして,以下のようなメモリマップで,メモリを表現することができる.
例えば,上のメモリマップのように,2 次記憶がメモリに張りついていてもよい.例えば, ディスプレイ情報が,「フレームバッファ」として張りついていたことを思いだそう.
しかし,通常は,「主記憶」(数十 M バイトから数百 M バイト)よりも「2 次記憶」 (数 G バイトから数十 G バイト) の方が膨大であり,メモリマップとしては, 「ほとんどが 2 次記憶」で,ほんの一部が「主記憶」という構成となる.そのため,以下の ような(仮想的な)メモリマップを考えることができる.
このように,アドレッシング(番地をふる)を,数 G バイト程度用意し,「2 次記憶」や「主記憶」を 必要に応じて貼り付けることにより,あたかも「メモリ」が数 G バイトあるようにみせる仕組みを 仮想記憶(virtual memory) という.ここで,常に対応する番地にメモリが存在するとは限らない ことに注意しよう.
ここで,仮想記憶を表現するメモリマップ上でのアドレスを,仮想アドレス(virtual address) という.一方,従来の主記憶にふられたアドレスを実アドレス(real address) という. 仮想記憶を扱う場合は,仮想アドレスと,実アドレスを厳密に区別するので注意しよう.
仮想記憶のメモリマップは,通常以下のような固定長のページ(page) に分割して管理する.
例えば,アドレッシングが 4 G であり(つまり,0 番地〜4G-1 番地まで番地をふる), 1 ページの大きさが 4 K バイトであれば,4G / 4K = 1M,1M ページあることになる.
仮想記憶の番地には,常にメモリ(2 次記憶も含む)が存在するとは限らない.そのため, 仮想記憶上のメモリをアクセスする場合には,「常にメモリが存在するかどうか」 を確かめることが 必要である.もし,メモリが存在しない場合,ページフォルト(page fault) という「割り込み」 が発生し,その割り込み処理手続きとして,アクセスしたい番地にメモリを割り当てる.
通常,ページを幾つか集めて,セグメント(segment) という単位でメモリを管理する. OS によっては,固定長のページのみを仮想記憶の単位として管理するものもあるが, 最近では,不定長のセグメントを単位として管理する方式が多い. セグメントは,通常意味のあるメモリ領域を指す.例えば,コードセグメント(code segment) は, プログラム自身(データ領域は除く)をおくメモリ領域を指し,スタックセグメント は, スタックを割り当てる領域を指す.データセグメント(data segment) は, データを割り当てる領域を指す.
セグメントを単位として仮想記憶管理を行う方式は,以下のようになる.
各セグメントの先頭番地は, セグメントディスクリプタテーブル(segment descriptor table) という表に格納されている. このセグメントディスクリプタテーブルは,実メモリ上の決められた位置にある. セグメントを参照するには,セレクタ(selector) というセグメントディスクリプタテーブル内の セグメントの先頭番地を指した変数を参照し,セグメントの先頭番地を取り出す.
セグメント内のどこを参照するかは,オフセット(offset) という変数に, セグメントの先頭からの相対番地を指定し行う.