メモリその6

前回は脱線したので、話を戻したい。この4GB分のアドレス変換、Windowsにおいては図7-16(上巻P498)の様な方法で変換される。ただこれをいきなり見ても判りにくいので、少しVMSを例に説明したい。

VMSにおける変換はこちらの図1に示す方法で行われるという話は既に行ったとおりだ。ここで、アドレスの上位23bitを管理するのがPage Tableと呼ばれるもので、各Page毎に1つづつ、Page Table Entry(PTE)が存在する。そこでアドレス変換機構は、

  1. Virtual Addressの上位23bit(厳密にはここで示した様に21bit)をキーに、PageTableを検索する。
  2. 目的のEntryを見つけたら、そのEntryに含まれるPage Frame Numberを取得する。
  3. 取得したPage Frame Numberと、元々のVirtual AddressのByte Offsetを組み合わせて、Physical Addressを生成する。

という形になる。当然ながら、この一連の処理はMMU(Memory Management Unit)というハードウェアで行うのが一般的だ。というのは、仮想記憶のOS上でアプリケーションが動く限り、猛烈な回数のアドレス変換が発生する。これを延々とソフトウェアでやっていたらメモリアクセスが恐ろしく遅くなるためで、最近のCPUでは通常1Clock、多くても2~3clockでこれが実施できるのが普通だ。逆に言えば、この変換メカニズムはハードウェアにOSがあわせる形になる。例えば通常の32bitにおける変換は図7-16、PAEモードにおける変換は図7-21(上巻P508)に示されているが、これをPhoto01、02と見比べてみると、要するにIA-32プロセッサのMMUが提供する方式にあわせてWindowsもアドレス変換を行っているだけだ、という事がご理解いただけよう。逆に言えばVMSのアドレス変換方法は、VAX ProcessorのMMUが提供する方法をそのまま利用しているだけとも言える。

Photo01:Intel 64 and IA-32 Architectures Software Developer's Manual Volume 3A System Programming GuideのFig.3-12より抜粋。

Photo02:同Fig.3-18より抜粋。

さて話をVMSに戻す。そんなわけでVMSにおけるアドレス変換の肝はPage Table内のPTEということになる。このPTEであるが、そのレイアウトは図1の様になっている。

図1:VMSのPTE。

それぞれの意味は、

  • 31 Valid:これが1だと、このPTEは有効なもので、0:20bitのPFNが正しく設定されていることを示す。
  • 27:30 Protection Code:これは、このPTEの属するVirtual Pageの保護モードを設定する。一例を示すと、0000はNo access Allowed、0010ならKernel Read/Write、0011ならKernel Read Onlyといった具合で、16のアクセスパターンが定義されている。このため、ページ割り当て時にそのページのアクセス状況を知りたい場合、このProtection Codeを参照すれば良い。
  • 26 Modified:これが1だと、そのページがModifyされている事を示す。Page outの際に、このPageをWritebackすべきかどうか、はこのbitで判断できる。
  • 25 Must be Zero:ここは常に0に設定される。
  • 20:24 Reserved:この部分はMMUでは利用されない。実際にはVMSはこの領域をOwner Access Modeのアクセス管理のために利用している。
  • 0:20 Page Frame Number:そのままである。

といった具合である。実メモリの割り当てとかその管理などは、全てこのPTEを参照しており、また各Processのメモリ管理もこのPTEを利用することになる。だから、例えばあるページをRead Onlyにするという操作は、PTEのProtection Codeを変更するという作業になる。このRead OnlyにされたページをProcessがModifyしようとした時には、そのProcessはやはりProtection Codeを参照し、アクセス違反であると判断してAccess Violationを発生するという訳だ。

さて、このPTEの集合であるProcess Tableはどこにあるか? という話だが、当然これは各Process毎となる。もう一度こちらの図1を見直して欲しいのだが、PTEへのPointerは、各ProcessのVirtual Page NumberをIndexとして生成される。これは各Process毎に同じものが利用される可能性がある(というか、普通、重なる)から、System WideでUniqueな番号とはならない。従って、Page TableもSystem Wideで作成するわけには行かないという話である。そこで、Processの生成時に、各Process用のPage Tableを一緒に作成することになる。