以前のエントリ3GBの壁についての個人的なまとめ(補足)でWindowsの3GBスイッチについてまたの機会に触れる、と書きました。今回はそれについてのエントリを起こそうと思ったのですが、よく考えるとその理解の前提となる「仮想アドレス空間」と「物理アドレス空間」についてまったく扱ってないということに気がつきました。
両者は非常に混同しやすく、このふたつの違いがわかっていないと3GBスイッチのエントリを読んでも意味不明なだけで終わってしまうでしょう。
というわけで、このエントリでは「仮想アドレス空間」と「物理アドレス空間」とは何であってどう違うのかを、私が調べた範囲でまとめてみようと思います。
ご注意
このエントリは話をわかりやすくするために、技術的な話を非常に簡略化して書いています。「正しい情報」を求める場合は、きちんとした文献に当たることをお勧めします。また、明らかな間違い・認識違いがある場合は指摘してくださると幸いです。
どうにもわかりにくい「二つ」のアドレス空間
私が過去に書いた3GBの壁についてのまとめ(前編)や3GBの壁についてのまとめ(後編)でもそうなのですが、通常「アドレス空間」と書いてあるときはその単語だけ見ても「物理」なのか「仮想」なのかはわかりません。前後の文脈から(もしくは文章のテーマから)読み手側が自分で理解する必要があります。
しかし、「仮想アドレス空間」と「物理アドレス空間」はまったく違うものでありながら、名前が非常に似ているため(もしくはただ単に「アドレス空間」と書かれるため)非常に混同されやすいもののようです。「アドレス空間」について調べ、それぞれ別の「仮想」と「物理」の資料が見つかって何だかさっぱり理解できない、資料によって書いてあることが全然違うと混乱してしまうこともあります。
これは仮想アドレスについての資料は多いのに、日本語の物理アドレスの資料があまり見つからない(見つかりにくい)というのも関係しているのかもしれません。こういう状態にならないためには、「仮想アドレス」と「物理アドレス」の違いをしっかり認識しておく必要があります。
物理アドレスとは名前の通り「物理メモリ」に割り当てるアドレス
OSの仕事の一つは物理メモリを管理すること
まず根本として、なぜメモリにはアドレスが割り当てられていないといけないのでしょうか?マシンにメモリを搭載し、OSをインストールしないでただ単に電源を入れた状態では、まだメモリにアドレスは割り当てられていません。BIOSから全体のメモリ容量がわかるだけです。
わかりやすいように例え話にします。
メモリの容量は現実世界でいう「土地の広さ」です。土地が広ければ広いほどたくさんの家が建てられますし、人もたくさん住めます。アドレスはそのまま「住所」になります。
物理アドレスとは物理的なメモリ(DIMM)に割り当てられる「住所」です。
もし土地に住所が割り当てられてなかったらどうなるでしょうか?当然郵便物(データ)を届けることは不可能になります。それに人が住み着いても住所がないのですから、外からまともにコンタクトをとることすら難しくなるでしょう。
そこで物理的なメモリ(土地)を管理するのがOS(Windows)の仕事になります。OSは土地(メモリ)に住所(アドレス)を割り当てて、きちんと「使える」ようにしなければならないのです。逆の言い方をすれば、管理外の土地(メモリ)は土地として存在していても利用することができない「荒れ地」と同じです。
32bit OSが管理できる広さは4GB(2^32 Byte)
通常の32bit OS(Windows)は物理アドレス空間を4GB持っています。つまり、広さとして4GBまでのメモリ(土地)までしか管理することができません。
例え4GB以上のメモリ(土地)を搭載しても、管理することができるのが4GBまでですから意味がないのです。これ以上の広さを管理したいなら、それ以上の管理区域を持っているOSである64bit OSやサーバ用32bit Windowsが必要になります。
物理アドレスを土地として考えた場合の「3GBの壁」
管理できない土地に施設は建設できない
せっかくなので、このたとえ話を「3GBの壁」にも当てはめて考えてみましょう。
前出のとおり、32bit OSが管理できる土地の広さ(メモリの容量)は4GBです。4GBの土地が管理できるのだから、4GBのすべてが利用できないのはおかしいと思うかもしれません。しかし、話はそう簡単ではないでのです。
人々が生活するには土地だけあればいいというものではなく、水道や電気などのインフラが整っていなければなりません。水道には浄水場、電気なら発電所という施設が必要になります。
OSが管理できる広さの限界が4GBですから、当然この領域内に浄水場や発電所を建てる必要があります。発電所の中に住宅を建てることはできませんから、単純に利用できる土地は減ります。
有限な土地をどう使うかが問題です
水道と電気だけで満足できるならいいですが、さらに環境をリッチ(便利)にしたいならガスの供給施設や下水道の処理施設も必要となるでしょう。新たな施設を建てれば建てるほど(PCのデバイスを増やせば増やすほど)、他に使用することができる土地は減ります。有限の管理区域の中で何とかやりくりしなければならないのが、Windows(と一般的なPC)が採用しているMMIOという仕組みなのです。(詳しくは3GBの壁についてのまとめ(後編)で。)
ちなみにWindowsだけそんな不便な仕組みを採用しているの?と考える方もいるかもしれませんが、これはWindowsに限った話ではなく(x86系アーキテクチャPCなら)LinuxもUnixもMacも同じ仕組みを利用しています。(ハードウェアの構成自体は同じでOSを変えることができるのですから、当然といえば当然なんですが。)
物理アドレスしか存在しない環境だと……?
何のためにメモリを増設するのか?
「物理アドレス空間」はOSが実メモリに割り当てる領域であることはわかりました。それではシンプルに物理アドレスだけが存在する環境だと問題があるのでしょうか?
メモリを増設する理由というのは、多分自分が使っているソフト(プログラム)を快適に動かすためでしょう。(もちろん「安くなったから」とか「Vistaが重いから」とかそんな理由もあるでしょうが。)メモリが十分にあればHDDにスワップファイルを作りに行くことはありませんし、ある程度重いプログラム(プロセス)をいくつも立ち上げても(CPUの処理が追いつけば)処理が遅くなったりはしません。
それではこれらのプログラムは、搭載されているメモリに直接アクセスしているのでしょうか?
現在のプログラムは直接物理メモリにアクセスしてない
物理メモリ自体にはすでにOSが物理アドレスを割り当てています。プログラムはその物理アドレスに直接アクセスしてデータを書き込む……、というわけにはいきません。
今のOSはほとんどがマルチタスクOS、つまりいくつものプログラムが同時にOS上で動いています。それぞれ違うプログラムAとBが同時に動いていると仮定しましょう。プログラムAが起動して、メモリの先頭からデータを5MBほど保存したとします。ではプログラムBが同じ挙動で、先頭から同じように5MBのデータを保存したらどうなるでしょうか?
メモリ上のデータが上書きされれば、プログラムAはエラーで止まってしまうでしょう。逆に上書きを拒否すればプログラムAは問題なく動いていくかもしれませんが、今度はプログラムBが止まってしまうかもしれません。
これを回避するには、それぞれA・Bのプログラムをメモリ領域が被らないように作るか、メモリ上にあるデータをHDDなどに一時的に退避するなどの挙動をプログラム側で実装(考慮)しなければいけません。同時にどんなプログラム(アプリケーション)が動くかは、開発者(プログラマ)にはわからないのにです。
また、利用者のPCがどれだけのメモリを搭載しているのかも開発者にはわかりません。世の中のPCはありとあらゆるスペックのものが存在しており、基本的にソフトは(最低環境だけは決めますが)OSが同じ限りどのPCでも動くことが求められます。
「メモリのどこを確実に使えるのかわからない」「メモリを使える限界量もわからない」では、ソフトの開発にあまりにも手間がかかります。(ありとあらゆる状態を考慮してプログラムを組まなくてはならない。)これでは効率が悪くてしょうがありません。
プログラムが直接物理メモリのアドレスにアクセスするのは、現在ではあまり現実的な手段とはいえないことが理解できたかと思います。(ただし、「仮想記憶」という概念や実装がされる前は、実際にこういうプログラムを組む必要がありました。もちろん当時は今よりずっとハードもソフトもシンプルでしたが。)
仮想アドレスとはプロセスのためにOSが用意する仮想空間
仮想アドレス空間とアプリケーションの関係
それでは「仮想アドレス空間」とは何なのでしょうか?それは、実際にOS上でプログラム(プロセス)がメモリを使うために必要になる領域です。
具体的に説明しましょう。
先ほどの例ではないですが、プログラムAとBが同時に起動したとします。OSはプログラムAとBに個別に2GBの仮想アドレス空間を割り当てます。つまり、プログラムが起動すると、それぞれプログラムとセットになる仮想メモリ空間が誕生するのです。
前出の物理アドレス空間はハードウェア(PC)とセットなのでひとつしか存在しませんが、仮想アドレス空間はプログラムの数だけ存在することになります。それぞれのプログラムからは、あたかも2GBのフリーなメモリ空間を与えられたように見えるため、プログラムはその空間を(常識の範囲内で)自由に使うことができます。
CPUとOSはその仮想空間のメモリアドレスを動的に物理アドレスに変換して、物理メモリにマッピング(配置)していきます。
ちなみにもっとわかりやすいですが、Linux版なので容量が違う図解はこちらからどうぞ。
スワップファイルは何のために存在するか?
「自分のPCにはメモリが2GBも搭載されてない」という方もいるでしょうが、別に問題ありません。これはあくまで仮想的な空間なので、物理的にメモリがどれだけあるかは関係ないのです。(実際に2GBの物理メモリが搭載できるようになったのは最近の話です。)
例えば物理メモリが512MBしかない状態でプログラムが1GBの仮想メモリ空間を使っても、残りの足りない部分は一時的なファイルとしてHDDに保存されています。これが「スワップファイル」の正体です。NT系のWindowsなら隠しファイルになっている「pagefile.sys」です。
なお、実際に32bit Windowsで作られる仮想アドレス空間の広さは2の32乗で4GBです。(広さ自体は物理アドレス空間と同じです。)しかし、それは半分の2GBずつユーザ空間、カーネル空間というものに分離されます。プログラムが直接扱えるのが前者のユーザ空間で2GB、残りの2GBはOSの制御部分となってプログラムからは手を出すことはできません。
以前に3GBの壁のまとめ補足で書いた「2GBの壁」とはこのことなのです。Windowsはデフォルトの状態でユーザ空間は2GBと定められているため、例えプログラムが2GB以上のメモリを使おうとしても、仮想空間以上にメモリを確保することは不可能です。プログラムからは物理アドレスに直接アクセスすることはできませんから。
まとめ
かなり長くなりましたが、話をまとめてみましょう。
- アドレス空間には「物理アドレス空間」と「仮想アドレス空間」の2種類がある
- 「物理アドレス」は実際の物理メモリに割り当てられるアドレス
- 「物理アドレス」はひとつしか存在しない
- 「仮想アドレス」はプログラム(プロセス)ごとに割り当てられているアドレス
- 「仮想アドレス」はプログラム(プロセス)の数だけ存在する
- 「物理アドレス」と「仮想アドレス」の相互変換はCPUとOSの大事な仕事のひとつ
- 「3GBの壁」は「物理アドレス空間」の枯渇が原因で発生する
- 「2GBの壁」はプログラムが使える「仮想アドレス空間」が2GBのため発生する
とりあえず今回はこんなところで。
この記事へのコメント
コメント機能を利用するにはログインする必要があります。「Disqus」または「Twitter」「Google」「Facebook」などのアカウントが使用できます。