Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume I/5-2
5-2 メモリアーキテクチャ
- IMPORTANT
- このセクションでは、Palm OS メモリアーキテクチャの現在の実装について説明しています。この実装は Palm OSの発展によって変更される可能性があります。ここで説明している実装固有の情報に依存せず、メモリを操作するための API を常に利用するようにして下さい。
Palm OSのシステムソフトウェアは32ビットアーキテクチャでデザインされています。システムは32ビットアドレッシングを用い、基本データ型は8、16、32 ビットとなっています。
32ビットアドレッシングにより、ソフトウェアはコードとデータを 4GB のアドレス空間に格納できます。このアドレス空間には、実行モデルに影響を与えずにハードウェアとソフトウェア両方の将来的な拡張に対応できるだけの余裕があります。広大なメモリ空間が利用できるにも関わらず、Palm OS は少量のRAMで効率的に動作するようデザインされました。例えば、最初の商用Palm ハンドヘルドは1MB以下、つまりアドレス空間の 0.025% に満たないメモリしか搭載していませんでした。
外部データバスが16ビット幅しかないにも関わらず、モトローラ 68328 プロセッサの 32 ビットレジスタと 32本の内部アドレスラインは32ビット実行モデルをサポートしています。このデザインにより、ソフトウェアモデルに影響を与えることなくコストを削減しています。プロセッサのバスコントローラは32ビットのリード&ライトを外側で自動的に複数の16ビットのリード&ライトに分割します。
Palm ハンドヘルドのそれぞれのメモリカードは 256 MB のメモリアドレス空間を割り当てられています。メモリカード0はアドレス $1000000 から始まり、メモリカード1はアドレス $2000000 から始まる、という要領になります。
Palm OS は利用できる RAM ストレージを2つの論理的な領域に分割します。ダイナミック RAM とストレージRAM です。ダイナミック RAM は一時的なメモリ確保による作業領域として、一般的なデスクトップシステムにインストールされた RAM と同じように使われます。利用できるメモリの残りの領域はストレージ RAM に指定され、デスクトップシステムにおけるディスクストレージのように使われます。
電力は常にメモリシステムに供給されているため、RAM の2つの領域はハンドヘルドの電源が“オフ”になってもその内容を保持しています(すなわち、これは低消費電力休止モードということです)。「 11 Palm のシステムサポート 」 の“Palm OS の電力モード”を参照して下さい。ストレージメモリの全ての内容はハンドヘルドがリセットされた場合でも保存されています。ブートシーケンスの一部において、システムソフトウェアはダイナミック RAM 領域を再初期化し、ストレージ RAM 領域はそのままにします。
RAMのダイナミック領域全体は動的アロケートのためのメモリを提供するヒープ領域として使用されます。このダイナミックヒープから、システムは大域変数、システムの(TCP/IP, IrDAなどに使用する)動的メモリ確保、アプリケーションスタック、一時的なメモリ確保、アプリケーションの動的メモリ確保(アプリケーションからMemHandleNew 関数などをコールした場合)などといった動的データのためのメモリを提供します。
ダイナミックヒープとして確保されているRAMは、実際にアロケートされているかどうかに関係なく、常に全体がその目的のために使用されます。ハンドヘルドの RAM におけるダイナミック領域のサイズは、動作している OSのバージョンや利用可能な物理RAMの量、およびプリインストールされている TCP/IP スタックや IrDA スタックといったソフトウェアが必要とする量によって変動します。現在利用可能な OS とハードウェアの組み合わせによるダイナミックヒープのサイズを表 5.1 にまとめます。
表 5.1 ダイナミックヒープのサイズ
RAM Usage | ≧OS 3.5,≦4 MB,TCP/IP & IrDA | ≧OS 3.5,≦2 MB,TCP/IP & IrDA | OS 3.0 > 3.3,> 1 MB,TCP/IP & IrDA (Palm III.) | OS 2.0,1 MB,TCP/IP only (Professional) | OS 2.0/1.0,512 KB,no TCP/IP or IrDA (Personal) |
---|---|---|---|---|---|
ダイナミックエリア全体 | 256 KB | 128 KB | 96 KB | 64 KB | 32 KB |
システムが使用する大域(スクリーンバッファ,UI用大域,DBリファレンスなど) | 40 KB(OS) | 40 KB(OS) | 〜2.5 KB | 〜2.5 KB | 〜2.5 KB |
TCP/IP スタック | 32 KB | 32 KB | 32 KB | 32 KB | 0 KB |
システムの動的確保(赤外線,“検索”ウィンドウ,一時確保) | variable | variable | variable amount | 〜15 KB(no IrDA in this OS) | 〜15 KB |
アプリケーションスタック(コールスタックと局所変数) | N/A (see note) | N/A (see note) | 4 KB (default) | 2.5 KB | 2.5 KB |
ダイナミックスペースの残り(動的確保,アプリケーションの大域変数,およびスタティック変数) | 184 KB | 56 KB | ≦36 KB | ≦12 KB | ≦12 KB |
- NOTE
- Palm OS 3.5 から、ダイナミックヒープのサイズはシステムが利用可能なメモリ量を基準として決まるようになりました。
ダイナミックヒープとして使用されない RAM の残りの部分は、1つ以上のストレージヒープとして設定されます。ストレージヒープには予定表やタスク、メモ、アドレス帳といった不揮発性のデータを保存するのに使用されます。アプリケーションはデータやリソースを操作する必要に応じて、データマネージャやリソースマネージャをコールしてストレージヒープにアクセスします。
ハンドヘルドにおけるストレージヒープのサイズと数は、動作しているOS、利用可能なRAMの物理的な量、およびユーザーアプリケーションソフトウェア ―― アドレス帳や予定表、あるいはサードパーティ製アプリケーション ―― が必要とするストレージによって変動します。
バージョン 1.0 と 2.0 の Palm OS では、ストレージ RAM を 64 KB ずつ分割して複数のストレージヒープにしていました。Palm OS 3.0 以降ではカード上のストレージ RAM を単一のストレージヒープとして扱います。Palm OS の全てのバージョンにおいて、単一のチャンクが利用できるデータストレージの最大サイズはシステムオーバーヘッドによって 64KB を少し下回るサイズに制限されます。
Palm OS の環境では、全てのデータはメモリマネージャのチャンクに保存されます。チャンクは 1 バイト〜 64KB 弱の連続したメモリ領域で、Palm OS メモリマネージャがアロケートします。(システムによるオーバーヘッドは流動的なため、全てのチャンクで利用可能な最大サイズを具体的に断言することはできません。)現在、全ての Palm の実装ではチャンクの最大サイズを 64KB 弱に制限しています。ただし、API にはこの制限はありません。ですから、将来的には緩和される可能性もあります。
各チャンクはヒープ内に存在します。ROMベースのヒープは移動不可能なチャンクだけを含み、RAMベースのヒープは移動可能なチャンクも移動不可能なチャンクも含む場合があります。RAMベースのヒープはダイナミックヒープかストレージヒープです。Palm OS のメモリマネージャはダイナミックヒープから(動的確保やスタック、大域変数などに使用する)メモリをアロケートします。Palm OS データマネージャはストレージヒープから(不揮発性のユーザーデータに使用する)メモリをアロケートします。
(ダイナミックデータの保持に使用されるメモリチャンクに対して、)ストレージデータの保持に使用される全てのメモリチャンクは、Palm OS データマネージャによって管理されるデータベースのレコードになっています。Palm OS 環境では、データベースは単純なメモリチャンクのリストおよび関連するデータベースヘッダ情報です。通常、データベース内のレコードには互いに論理的な関連があります。例えば、あるデータベースはアドレス帳の全エントリを保持しており、別のデータベースは予定表の全エントリを保持している、などです。
データベースはデスクトップシステムにおけるファイルのようなものです。従来のファイルシステムでファイルの作成、削除、オープン、クローズができるように、Palm OS のアプリケーションは必要に応じてデータベースの作成、削除、オープン、クローズができます。全て同一のメモリカード上にある限り、データベースのレコードが置かれる場所に制限はありません。データベースのレコードは同じメモリ上で1つ以上の他のデータベースのレコードとともに散在させることができます。
データベースを使ったデータの保存はPalm OSメモリマネージャのデザインに良くフィットしています。データベース内の各レコードは実はメモリマネージャのチャンクなのです。データマネージャはデータベースレコードの追加、削除、リサイズのためにメモリマネージャを使うことができます。ダイナミックヒープを除く全てのヒープは不揮発性なので、データベースレコードはダイナミックヒープ以外の全てのヒープに保存できます。レコードはメモリカードのどこにでも保存できるため、データベースは物理RAM上の複数の不連続な領域に分散させることができます。ただし、同じデータベースのレコードは全て同じカード上になければなりません。
データベースレコードの操作の仕方を理解するためには、メモリマネージャがメモリチャンクをアロケートし、管理する方法について知るのが良いでしょう。それについては次のセクションで説明しています。
ヒープの概要
- IMPORTANT
- このセクションでは、Palm OS メモリアーキテクチャの現在の実装について説明しています。この実装は Palm OSの発展によって変更される可能性があります。ここで説明している実装固有の情報に依存せず、メモリを操作するための API を常に利用するようにして下さい。
ヒープは連続したメモリ領域であり、1つ以上のメモリチャンクを含むものであることを思い起して下さい。アプリケーションがメモリを使って処理(アロケート、リサイズ、ロックなど)を行なう場合、通常はメモリチャンクを使って処理をしています。アプリケーションは新しいメモリチャンクをアロケートする際、ストレージヒープとダイナミックヒープのどちらから確保するかを指定できます。メモリマネージャはそれぞれのヒープを別々に管理しており、断片化したヒープを必要に応じて再構成し、空き領域をマージします。
Palm OS環境のヒープはヒープIDによって区別されます。ヒープIDは一意な16ビットの数値で、メモリマネージャがPalm OSのメモリ空間上でヒープを識別するのに使用しています。ヒープIDは0から始まり、1ずつインクリメントされます。番号はカード0のRAMヒープから付与され、次にカード0のROMヒープに、続いて後続のカードのRAMヒープおよびROMヒープに順に付与されます。ヒープIDのシーケンスは連続しており、番号がスキップされることはありません。
カード0上の最初のヒープ(ヒープ0)はダイナミックヒープです。このヒープは Palm ハンドヘルドがリセットされるたびに再初期化されます。アプリケーションが終了すると、システムはそのアプリケーションがヒープにアロケートしたチャンクを全て開放します。その他の全てのヒープは不揮発性で、次のソフトリセットまでの間その内容を保持します。
Palmハンドヘルドが複数のダイナミックヒープを使える場合、カード0上の最初のヒープ(ヒープ0)はアクティブなダイナミックヒープになります。他の全てのダイナミックヒープになれるヒープは無視されます。例えば、複数のカードをサポートする将来のPalmハンドヘルドに、それぞれがダイナミックヒープを持つ2つのカードを装備することは可能です。その場合、カード0に存在するダイナミックヒープだけがアクティブになります。システムは他のカードのヒープはダイナミックヒープとして扱いませんし、これらのヒープにヒープIDを割り当てることもしません。後続のストレージヒープには、常に最初にRAM、次にROMという順で連続するIDが割り当てられます。
- NOTE
- Palm OS 3.5 では、ダイナミックヒープのサイズはシステムが利用できるメモリの量によって決まります。
メモリチャンクの概要
メモリチャンクは移動可能な場合もありますが、できない場合もあります。アプリケーションは可能な限り移動可能なチャンクにデータを保存するべきです。それは、メモリマネージャが必要に応じてチャンクを移動し、連続した空き領域を作成してアロケート要求に応えられるようにするためです。
メモリマネージャは移動不可能なチャンクをアロケートする場合、そのチャンクのポインタを返します。ポインタは、単純にそのチャンクのメモリ上のアドレスです。チャンクは移動できないため、そのポインタはチャンクのライフタイムにおいてずっと有効です。従って、ポインタはアロケートを要求した呼び出し元に“そのまま”渡すことができます。
メモリマネージャが移動可能なチャンクをアロケートする場合、移動不可能なチャンクの場合と同じようにポインタを生成しますが、ポインタを呼出し元に返すわけではありません。そのかわり、チャンクを指すポインタ ―― これをマスタチャンクポインタと呼びます ―― を、ヒープ内の全ての移動可能なチャンクを追跡するために使われるマスタポインタテーブルに格納し、そのマスタチャンクポインタへの参照を返します。このマスタチャンクポインタへの参照はハンドルとして知られています。移動可能なチャンクを要求した呼出し元にメモリマネージャが返すのは、このハンドルです。
ハンドルの使用はポインタの直接使用と比較するとわずかにパフォーマンス上のコストがかかりますが、そのかわりメモリマネージャはアプリケーションがデータを保存しているかもしれないチャンクへの参照を無効化することなく、ヒープ内でチャンクを移動させることができます。アプリケーションがデータの参照にハンドルを使用している限り、断片化の際にメモリマネージャがチャンクを移動する場合でもチャンクへのマスタポインタを更新するだけで済みます。
アプリケーションは通常、チャンクの内容を参照したり操作したりする短い間だけチャンクのハンドルをロックします。チャンクをロックするこの処理は、メモリマネージャに対してそのデータチャンクが動かせなくなったことを知らせています。アプリケーションがデータチャンクへの参照を必要としなくなったら、断片化を最小限に抑えるために、ただちにハンドルをアンロックするべきです。
- IMPORTANT
- 全てのハンドルはシステムがリセットするまでの間しか有効でないことに注意して下さい。システムがリセットされると、ダイナミックメモリ領域は全て再初期化され、アプリケーションは再起動されます。従って、ハンドルをデータベースのレコードやリソースに格納することはできません。
メモリカード上の各チャンクは、実際にはローカルIDと呼ばれるカード別の参照によって識別されます。ローカルIDはカードのベースアドレスからシステムが算出したデータチャンクへの参照です。移動不可能なチャンクのローカルIDは、単純にカードのベースアドレスからのチャンクのオフセットです。移動可能なチャンクのローカルIDはカードのベースアドレスからチャンクのマスタポインタへのオフセットですが、最下位ビットがセットされます。チャンクは常にワード境界に揃えられるため、移動可能なチャンクのローカルIDだけに最下位ビットをセットすることができます。実行時にカードのベースアドレスが一度決定されると、ローカルIDはポインタまたはハンドルに素早く変換されます。
例えば、特定のデータレコードを指すハンドルを必要としている場合、アプリケーションはデータマネージャをコールして適切なデータベースからインデックス指定でレコードを取得します。データマネージャはデータベースヘッダからレコードのローカルIDを取得すると、それをレコードのハンドルに変換します。レコードのハンドルがデータベース自体に保存されることは決してありません。
現在利用できる Palm ハンドヘルドは複数のカードをハードウェア的にサポートしませんが、ローカルIDの使用については将来のハンドヘルドでユーザーがメモリを着脱できるよう、ソフトウェア的なサポートがなされています。ユーザーがメモリカードを別のベースアドレスを持つスロットに移動すると、そのカード上のメモリチャンクを指すハンドルは変わってしまうかもしれません。しかし、そのチャンクに関連付けられたローカルIDは変化しません。
- IMPORTANT
- メモリカードと拡張カード(SDカードやメモリースティックなど)を混同しないように注意して下さい。拡張カードには別の API を介してアクセスします。詳細は「 7 拡張カード 」を参照して下さい。