読者です 読者をやめる 読者になる 読者になる

昔のMacintosh仕組み1 メモリ管理

プログラミング 雑談

ちょっと今日から何回か、昔のMacのプログラミングとかOSの構造とかについて話していきたいと思う。初期のMacのUIはいまのパソコンの殆どに影響与えてるし、ぱっと見いまのWindowsLinuxGUIと変わらないけど、そこには昔ならではの違いとかいろいろあるので面白いと思うんだよね。

 

 

 

Macintoshはほぼ初めてのGUI専用パソコンだった。ほぼというのは、その前年に同じAppleからLisaが出ていたからだけど。Lisaはそのプロジェクトから追い出されたジョブズがすげえdisったのでほとんどなかったことにされている。

 

それはさておき、Macにおいてもプログラムを組む際、ヒープ領域にメモリブロックを確保する必要はあるわけで、そのためのAPIが用意されていた。NewPtr()とNewHandle()である。NewPtr()は、引数に指定したバイト数のメモリブロックを確保し、その先頭アドレスを返す。HewHandle()は、指定したバイト数のメモリブロックを確保し、その先頭アドレスを、OSが管理するマスターポインタエリアに格納し、そのマスターポインタが格納されているアドレスを返す。Macにおいて、「ポインタ」は領域の先頭アドレスを指し、「ハンドル」は「領域のアドレスを収めたマスターポインタのアドレス」を指す。つまり、ハンドルというのは二重参照ポインタである。

 

ハンドルにアクセスするためには二回アドレス解決しないといけないのでポインタより遅い。なぜそんな仕組みがあったかというと、Macのメモリが少なく、また、MMUなんて高級なハードウエアを備えていなかったことによる。少ないメモリで、ハードの助けを借りずなんとかやりくりするための工夫が「ハンドル」という仕組みだったのだ。

必要な領域を次々確保していった場合、いつかメモリが足りなくなる。NewHandle()でメモリを確保する際、必要な連続領域が残されていなかったらどうなるか。

その場合OSはヒープ空間上でメモリ領域を「ごそっと」ブロック転送するのだ。必要な領域を確保。必要なくなった領域を開放という作業を続けると、メモリ上に島のようにあちこちにブロックが残っているが、連続した領域が必要なだけ残らないという状況になる。つまりメモリの断片化である。このとき、空き領域を詰めて、大きな空きを確保しようとする。昔NetNews上でこの話をしたら、UNIX使ってる人たちに「うそ!、そんな原始的なことやってんの??」と驚かれた。実際やってたんです。MMUなかったからね。しょーがねえ。

 

ヒープ上でメモリブロックが移動すると、マスターポインタが書き換えられる。なので、ハンドルから二重参照でアクセスする限りなんら問題は起きない。けれど、ビットマップ画像の書き換えなど、大量のデータを高速に扱う必要がある場合、ハンドルを毎回二重参照するのではなく、ローカル変数にマスターポインタの値を入れて使うことがよくあった。こういう場合ハンドルを「ロック」するのだ。ロックされたハンドルはOSによって移動させられることはない。もちろんメモリ資源の有効活用のため、操作が終わったらすぐに「アンロック」する必要があった。

さらにハンドルには、「パージ可能フラグ」という属性があって、これをONにしていると、メモリブロック移動で必要な領域を確保できない場合、パージ可能なハンドル領域を「潰す」ことになっていた。これをONにするのは、ハンドルのデータをディスクに書き出すなどして、あとで復旧できる状態のものに限られた。つまり、OSの都合で消されてもアプリケーションの責任で復旧できるメモリ領域だけこのフラグをONにしていたのだ。

なお、GUIの象徴ともいえるウィンドウの各種属性を保持するWindow構造体に関して、Macintoshはハンドルではなく、ポインタで確保していた。画面表示の根幹に関わる部分なので少しでも高速化したかったのだと思う。そのおかげで、初期Macのプログラムでは書類ウィンドウを予め決めた数しか開けないというアプリケーションが多かった。ハンドルでないポインタ領域は移動もパージもできないので、メモリ断片化しないためには、プログラム起動時にWindow構造体を必要なだけ確保しておく必要があったのだ。

 

そういうふうに、プログラマがメモリ領域の移動や開放を意識する必要があったため、Cが普及し始めた頃、UNIXを使う大学生や研究者がMacmalloc()を使って酷い目に遭う状況が頻発した。malloc()はポインタを返す関数なので、当然Macにおいては内部でNewPtr()を使用している。つまりメモリが足りなくなったときにハンドルみたいによろしくやってくれないのだ。当時「Macmalloc()使うなんて素人が!」的な視線が浴びせられた。結果としてUNIX使いからMacに対するヘイトが溜まってしまった事情があったりする。なんというか文化の違いだよねえ。