メモリその4

さてSwapの話はこのくらいにして、少しMemory Address Translationについて触れてみたい。ここで言うTranslationは、ProcessのVirtual Addressと、実際のPhysical AddressのTranslationの話である。Inside Windowsでは「7.5 アドレス変換」(上巻P495~)で説明されている内容だ。

Virtual AddressとPhysical Addressは全く独立に管理される。これにより、各Processは見かけ上フラットな4GB(32bitの場合。64bitだと8192GB)のアドレス空間を利用できるため、プログラムを記述する際に物理的なMemory配置を気にする必要は一切無いし、デバイスドライバなどごく一部の処理を除き、物理的な配置を知ることも出来ない。一方Systemは、各Processが必要とするMemoryをPage単位で自由にMappingできる。必要なら、利用するMemoryのRe-Allocationも可能だ。このため、Memory空間を有効に使うことができるようになる。

図1:VMSでのAddress Translation。

さてそのAddress Translationだが、VMSのそれはWindowsに比べるとずいぶん簡単な機構になっており、その分理解がしやすい。図1はこのVMSにおけるAddress Translationをまとめたものだ。VMSの場合、1Page=512Bytesの固定となっていた関係で、Addressは下位9bitと上位23bitに分かれ、更に上位23bitのうち2bitがRegionに割り当てられているため、実際は2bit / 21bit / 9bitという形に分割される。さて、このうち上位2bitは、メモリアドレスの分類を行うものである。具体的には、

  • 00:そのメモリ領域はP0 Page Tableを利用して管理されるP0 Address Spaceにあたる。実際に各User ProcessがProgramを配置するのがこのP0 Address Spaceで、Program Regionなどとも呼ばれる。
  • 01:そのメモリ領域はP1 Page Tableを利用して管理されるP1 Address Spaceにあたる。ここは各User Processが利用するStack Areaや、VMS Kernelとの通信に利用する領域などが配される。この領域はControl Regionとも呼ばれる。
  • 10:このメモリ領域はSPT(System Page Table)を利用して管理されるSystem Space Addressにあたる。ここは要するにVMS Kernelのみで利用される領域である。
  • 11:このメモリ領域はUndefinedであり、ここにアクセスするとメモリアクセス違反が発生する。

という4つに分類される。つまり、Processから見える4GB分のうち、下位2GB(0~1GBがP0 Address Space、1GB~2GBがP1 Address Space)が各Processに開放され、残り2GBがSystem管理(うち1GBがKernel、残り1GBがReserved)という形になる。要するに図2の様な構造だ。これをみて、ぱっとInside Windowsの図1-4(上巻P18)を連想する人は多いだろう。実際、32bit Windowsのデフォルト構成と全く同じレイアウトである。

図2:VMSにおけるAddress Mapping。

実のところこれは、VMSから継承云々というよりも、技術的要件を考えると必然的に決まるレイアウトである。まずOS KernelとUser ProcessのAddressを分離しないと、色々面倒なことになる。勿論KernelとUserではProcessが異なるから、同じAddressにしたからといってすぐさま危険になるわけでは無いが、Adressそのものを分けてしまえば、仮に特権を操作されてもまだAdressがバリアになるために、安全性が高まる。

次は上位下位どちらにおくかだが、x86を含む大多数のProcessorは0x00なり0x10なりといった低いアドレスからプログラムを開始するのが普通であり(だからこそ、Initial Program Loaderは物理的に一番先頭に置かれることになる)、そう考えるとUser Processを低位Addressに配置するのが自然だ。

後は分配だが、なにしろ1990年前後といえば物理メモリが数MBという時代だから、まぁ4GBを2等分して2GBづつに割り振れば当面は十分という考え方に無理はないだろう。実際、エンタープライズ向けアプリケーションとかデータベースなどを除くと、殆どのプログラムは2GBのアドレスでそこそこに動作している。Windows 2000以降は起動時に/3GBオプションを付けることで、User Processに3GBを割り当てることが可能になったが、これは要するに図2でReservedになっている分をProcessに割り当てた、という話であって、PAE36などとは話が異なっており、図2の枠組みの範囲でちょっと拡張したという話でしかない。

実際、Windows Vistaの様なメモリ馬鹿食いOSが出てしまったことで、ぼちぼち32bitでは色々限界が見えてきてしまったが、それを除くと今のところはこの枠組みで十分足りているし、リアルタイム系OSなどは2010年の時点でもこれで十分だろう。Linuxなども、32bitに関してはほぼ同じ(ただしKernelは1GB、User Processが3GB)で実装されている。