仮想記憶
[Wikipedia|▼Menu]
仮想記憶の概念図

仮想記憶(かそうきおく、英語: Virtual Memory、バーチャルメモリ)とは、コンピュータ分野におけるメモリ管理の仮想化技法の一種であり、オペレーティングシステム (OS) などが物理的なメモリを、アプリケーション・ソフトウェアプロセスなど)に対して、専用の連続した主記憶装置に見えるように提供する。

この技術により、物理的な主記憶装置に加えてハードディスク装置等の補助記憶装置を併用すれば、物理的な主記憶装置よりも大きな仮想メモリを提供する事ができる。またアプリケーション・プログラム側は、物理メモリ上のアドレスを意識しなくて良いため、マルチタスクの実現が容易である。このため現代のオペレーティングシステムの多くが仮想記憶をサポートしている。

仮想的に与えられたアドレスを仮想アドレス (virtual address) または論理アドレス (logical address)、実記憶上で有効なアドレスを物理アドレス (physical address) または実アドレス (real address) という。仮想アドレスの範囲を仮想アドレス空間、物理アドレスの範囲を物理アドレス空間という。
概要

仮想記憶の実装(仮想記憶方式)には、大きく分けてセグメント方式ページング方式の二種類がある。ちなみに68000システムでは、68451(セグメント方式)と、68851(ページング方式)のメモリ管理ユニット (Memory Management Unit、MMU) が準備されていた。

一般にページング方式の方がよく使われている。これにより、メモリスワッピング(あるいは匿名メモリページング)と仮想記憶が結びつけられる。メモリスワッピングとは、一次記憶装置内のメモリページを二次記憶装置(のスワップファイルあるいはスワップパーティションと呼ばれる場所)に書き出して、より高速な一次記憶装置を他のプロセスが使えるように解放することである[1]

Windows系OSのうち、#Windows NT系ではページング方式の仮想記憶を採用しており、システムUI上では「仮想メモリ」という名前の設定項目が用意されているが、このシステム設定項目はページングファイル(ストレージへのメモリスワップ)に関するものである[注釈 1]。アプリケーションおよび多くのシステムプロセスは常に仮想アドレスを使用してメモリを参照する。OSカーネルのコア部のみがアドレスの仮想化をバイパスすることができ、実アドレスを直接使用できる。たとえ稼働中の全プロセスによって要求されるメモリが、システムにインストールされているRAMの容量を超えていなくても、仮想記憶は常に使われている[2]

Unix系システムでもスワップファイルやスワップパーティションなしで仮想記憶を使用することが可能である。従って主記憶装置以上の大きな記憶領域を仮想的に使用できるようにすることは仮想記憶の主な目的ではあるが、本質ではないとも言える。本質は、不連続な物理メモリ領域を連続な仮想メモリ領域にマッピングすることであり、複数のプロセスがそれぞれ固有の連続な仮想メモリ領域を割り当てられる点である。これによって他のプロセスのことを気にせずに動作できる環境が提供されている。そういった意味で、仮想機械がゲストOSに対して提供していることと、仮想記憶がユーザープロセスに提供していることは等価である。仮想記憶は物理メモリのフラグメンテーションを隠蔽することでアプリケーションのプログラミングを容易にする。すなわちカーネル記憶階層の管理を委任することで、プログラムが明示的なオーバーレイの制御を行う必要性を排除している。

技術的には、仮想記憶を使うことにより、ソフトウェアが動作するメモリアドレス空間のサイズとアドレス範囲は当該コンピュータの物理メモリ領域には必ずしも縛られなくなる。仮想記憶を適切に実装するには、CPU(あるいはそれに付随するデバイス)がOSに対して仮想メモリを物理メモリにマップする(対応付ける)手段を提供し、主記憶(物理メモリ)に対応していない仮想アドレスにアクセスしたことを検出する手段を提供して必要なデータをスワップインできるようにしなければならない。CPUの支援なしで仮想記憶を提供することも可能だが、その場合は上述の機能を提供するCPUをエミュレートするだけであって、本質的には同じことである。アドビの一部のアプリケーションのように、アプリケーションプログラムが自前で仮想記憶機構を持つ例もある[3][4]

ソフトウェアによって仮想記憶を実現することは、本来ハードウェアで実現できる機能をあえてソフトウェアで行おうとしているので一見非効率に思える場合がある。しかし、この見方は場合によっては誤りである。なぜならページ方式やセグメント方式では仮想アドレス空間に対する広がりを持たせているので、例えば画像などを扱う場合には単にアドレス空間方向への広がり=すなわち水平方向への広がりしか持たない。だが画像に対する操作は、特定の2次元空間=面的な広がりを持っている。ここにソフトウェアで仮想記憶を実施するに当たって、面的な広がりをメモリ参照の局在性としてみなすと、単なる仮想記憶よりも性能の向上が期待できる。
背景

まず、以下の議論の前提とする、簡略化した典型的な記憶装置の階層構造のモデルを述べる。

CPU内のレジスタ。CPUのクロック速度で動作するため、最も高速である。レジスタの使用は一般に呼出規約の制限下にあり、コンパイラによる管理に任せられる。大きな容量はないため(32ビットあるいは64ビット、現代的なマイクロプロセッサでは16本?普通は100本前後)次の計算が使えるように明け渡す必要があり、データを長期間保持させることは通常はできない[注釈 2]。内部的にはレジスタ・リネーミングを行っていることもある。

CPU内かCPUに隣接したキャッシュメモリ。通常はある種のSRAMを使用。レジスタに次いで高速であるが、容量は128kバイト?数メガバイト程度に留まる。@media screen{.mw-parser-output .fix-domain{border-bottom:dashed 1px}}近年[いつ?]では1次キャッシュから3次キャッシュまでもがオンダイという場合もあり、ここで示した容量などに特に拘る意味は無い。

主記憶装置(通常はDRAMを使用)は、プログラミング上CPUが直接リード/ライトできる。キャッシュメモリに比べると速度は落ちるものの、より大きな容量(数百メガバイト?数ギガバイト)を装着できる。

補助記憶装置としての磁気ディスク装置は、機械的な動作を伴うため、主記憶装置と比べても桁違いに低速だが、数十ギガバイト?数十テラバイト以上と容量が大きい。

主記憶装置とキャッシュメモリのどちらを使用するかは、一般にハードウェアに任せられているため、プログラマからはどちらも同じ物理メモリとしてしか見えない(しかし性能への影響は大きいので、高性能計算など、キャッシュヒット率を考慮してコードを書くこともある)。ハードウェアの動作としては、まずキャッシュメモリをアクセスし、さらに必要ならキャッシュメモリと主記憶とのやり取りを行う。

多くのアプリケーションは、情報(実行ファイルの命令列やデータ)がなるべく物理メモリ上に格納された状態でアクセスできることを要求する。これは特に見かけ上並列に複数のプロセス/アプリケーションを同時実行するオペレーティングシステムでは重要となる。全実行中プログラムが必要とする物理メモリ量が実装されている物理メモリ量より大きい場合、当然の結果として情報の一部をディスクに退避し、必要に応じてその内容を物理メモリに戻して使用することになる。しかし、これを実現する手法は様々である。

ひとつの方法として、アプリケーション自身が物理メモリ上に置くべき情報の範囲を決定し、補助記憶装置との情報のやりとりも制御することが考えられる。プログラマはプログラム(およびデータ)のどの部分が現時点で必要か不必要かを判断し、それらの領域の物理メモリへのロード(あるいはアンロード)を必要に応じて行わなければならないだろう。この手法の欠点は、各アプリケーションのプログラマがそのような設計/実装/デバッグに時間を費やす必要がある点であり、アプリケーションそのものに集中できなくなってプログラミング効率が低下する。また、あるプログラマがある時点で物理メモリ上に置くべきデータなどを決定しても、それが例えば、どうしても全物理メモリが必要となった場合など、他のプログラマの決定と衝突してしまう危険がある。仮想記憶が普及する以前のオーバーレイ方式がほぼこれに相当する。

別の方法として、データの参照ポインタではなく何らかのハンドルで行う方式である。OSはそのようなハンドルと対応するデータを物理メモリにロードしたり、逆に補助記憶装置に移したりする。この方式の欠点は、アプリケーションのコードが非常に複雑になる点、アプリケーションがうまく振舞わなければならない点(必要なデータを物理メモリにロックする機能が必要になるだろう)、標準ライブラリが大きなメモリを確保しておいてアプリケーションのメモリ確保要求に応えるという機能を使えなくなる点などが上げられる。この方式の既存の例としてはMicrosoft Windows 3.1が有名である。

現代の解決策は仮想記憶方式の使用である。特別なハードウェアとOSの組合せにより、主記憶容量が大きくなったように見せ、各プログラムが自由気ままに空間を広げて使用することを可能にする。動作中の他のソフトウェアからは、仮想記憶機構の内部の動きは見えない。一般に仮想的な主記憶容量はほとんどどんな大きさにもできる。ただし、アドレスそのもののサイズによる制限がある。32ビットシステムでは、仮想アドレス空間サイズは全体で 232バイト、つまり4ギガバイトである。64ビットの場合、アドレスは64ビットや48ビットといったさらに大きなものになっている。多くのオペレーティングシステムは仮想アドレス空間全体をアプリケーションに使わせることはなく、一部をカーネル空間にすることでカーネルからユーザ空間に容易にアクセスできるようにしている。ただし、これは絶対必要な機能ではなく、OSによっては仮想空間全体をユーザー空間としている。

仮想記憶によってアプリケーションプログラマの仕事はずっと単純になる。アプリケーションが必要とするメモリ容量を気にする必要はなく、必要なサイズの主記憶が使えるように見え、仮想アドレス空間全体の好きな場所にデータを配置することができる。プログラマは主記憶と補助記憶の間でデータをやりとりするのを気にしなくてもよい。


次ページ
記事の検索
おまかせリスト
▼オプションを表示
ブックマーク登録
mixiチェック!
Twitterに投稿
オプション/リンク一覧
話題のニュース
列車運行情報
暇つぶしWikipedia

Size:78 KB
出典: フリー百科事典『ウィキペディア(Wikipedia)
担当:undef