借り初めのひみつきち

仮ブログです。

x86 の限界を考えてみた。

一般に 32bit CPU の扱えるメモリの限界は 4GB です。

これはアドレスバスに流れている信号が2進数で 32 本あるため、2^32 = 約40 億種類の異なるメモリにアクセスできることからきている数値です。*1

386 CPU は 32bit CPU ですが完全なアドレスを表現するためにはセグメントセレクタも必要になるので*2、実際には 16bit + 32bit = 48bit = 約256TB のアドレスが存在するような気がします。

実際のセグメントセレクタは下位 3 ビットが権限チェックや GDT と LDT のために使われており、セレクタインデックスとして実際に使える値は 13bit = 2^13 = 約8000種類です。
LDT はアプリがすべて自由に使えると仮定しても、 GDT にはシステムの動作のためにいくつかのセレクタが必要になるのですべてを自由に使えるわけではありません。 約8000~約16000 程度のセレクタが使えることになります。

理屈の上では約8k~16K個のセレクタそれぞれに 4GB の空間が存在し得るわけですが、本当に 4GB x 16K = 64TB アクセスできるのでしょうか?

386 CPU には 32bit のリニアアドレス空間があり、セグメンテーションでアクセスできるのはその 4GB 空間から切り出した一部(または全部)になります。

セグメントAに 4GB 割り当てた場合、セグメントBにアクセスしたくてもセグメントを割り当てる場所がもうリニアアドレス空間に残っていないので、セグメントAとセグメントB両方に 4GB 割り当てて同時にアクセスすることはできません。4GB x 16K =64TBは幻想です。

しかし、セグメントサイズが2GBの場合は4GB空間に2つのセグメントを確保できるので、この2つのセグメントは共存可能です。

ここで新たにセグメントCにアクセスしたい場合はどうなるでしょうか。

もう4GBのリニアアドレス空間は残っていないので割り当てることができません。ここで仮想メモリの出番です。

カーネルがセグメントAかBの使用頻度が低そうな方をどこかに退避して2GBの空きメモリを作った後セグメントCとして割り当て直せばセグメントABCの合計6GBにアクセスできます。

では本当にこの方法でどんどんメモリを増やすことが可能かというと、実際には仮想メモリを管理するカーネルが常にリニア空間上に存在していなければならず、さらに最低でもコードセグメントとデータセグメントはそれぞれ同時にリニア空間に割り当てられていないと問題があるので1セグメント2GBはちょっと大きすぎます。1GBくらいなら可能でしょうか。その場合は 1GB x 約8K~16K = 約8TB~16TB の仮想メモリを扱えるということになります。

なお、一般にプログラムコードより扱うデータの方が多くのメモリを必要とするので、4GBのリニアアドレス空間カーネル1GB・ユーザーコード1GB・ユーザーデータ2GBとして分割した場合は、2GB x 約8K~16K = 約16TB~32TB になって上記の約2倍わりあて可能です。
さらに、コードに1GBも必要ない場合は、カーネル512MB・ユーザーコード512MB・ユーザーデータ3GB・・・ともっと多くのメモリを扱えます。

なおこの場合、セグメントをまたがったデータのコピーはできません。

いくつかのセグメントが同時にリニア空間に割り当てされていないといけないのはなぜでしょうか?

CPU は常にメモリから命令を読み込んで動作しているので、実行中のプログラムは常にメモリ上の見える場所に存在する必要があります。
一方でメモリアクセス命令は対象になるメモリが存在していないと実行できません。
仮想メモリで現在使っていないセグメントを切り替えたとしても、今現在実行している命令と今現在アクセスしているメモリの両者は常にメモリ上に存在していないと実行できません。
セグメンテーションを使った仮想メモリはセグメント単位で退避・復帰しないといけないので、たとえ今現在必要なメモリが数バイトであっても1セグメントすべてリニア空間に割り当てる必要があります。

なお、PAE を使ったメモリ拡張でも x86 にはリニアアドレス空間 4GB の束縛があるので、本当に 2GB 以上のメモリアクセスが必要なら素直に64bit OSを使いましょう。

実用性はともかく、386で数TBの仮想メモリが扱えそうなことがわかりました。

*1:なお、現在主流のバイトマシンの場合は 4G バイトになりますが、むかし存在したワードマシンの場合はバイト単位だとバイトマシンの4倍の 16GB 扱えることになります。32bit のワードマシンが存在するかどうかは知りませんが・・・

*2:ほとんどの32bit OSではなかったことにされていますが