高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Note TN1128
Understanding Open Transport Memory Management

目次

このテクニカルノートでは Open Transport の割り込み対応メモリ管理システムの動作原理とあなたのソフトウェアで効果的に利用する方法を説明します。

このテクニカルノートは、Open Transport のクライアントまたはカーネルコードを開発する上級プログラマを対象にしています。

[2001年1月9日]



OT メモリ管理入門

Open Transport は割り込み時に呼び出し可能なメモリ割り当てルーチンを多数用意しています。OTAllocMem、OTAllocMemInContext、OTAlloc、OTAllocInContext、OTAllocSharedClientMem、OTAllocPortMem です。どんな場合にどのルーチンを使えばよいか(また、こうしたルーチンが Open Transport や Mac OS 管理下のメモリにどう影響するか)を知るには、OT のメモリ管理システムを理解する必要があります。

強力なメモリプール

OT メモリ管理は 4 つのメモリプールの上位に位置します。

  1. クライアントプールは InitOpenTransport(または InitOpenTransportUtilities)を呼び出したプログラムにそれぞれ割り当てられます。そのプログラムの OT メモリ割り当て要求を満たすもので、プログラムが CloseOpenTransport を呼び出すと(明示的またはアプリケーションの終了で)破棄されます。
  2. 共有クライアントプール(ネイティブプールとも呼ばれる)は最初のプログラムが(通常は AppleTalk プロトコルスタックがブートシーケンスの最初のほうで)InitOpenTransport を呼び出すと割り当てられます。OT のクライアントライブラリが割り当てるメモリの大部分はこのプールを使用します。
  3. カーネルプールは、OT カーネルのロード時に割り当てられます。これは OT カーネルやプラグインが使用します(例えば STREAMS のモジュールやドライバ。)
  4. ポートプールはプログラムがはじめて InitOpenTransport または InitOpenTransportUtilities を呼び出すと割り当てられます。このプールはポートに関する情報を保持します。これはカーネルプールとは違います。ポートスキャナは、カーネルをロードしなくても(つまりカーネルプールがなくても)使えます。

Open Transport メモリプールは Apple Shared Library Manager(ASLM)TStandardPool クラスで実装され、このクラスの属性のいくつかを継承します。

  1. どのプールも常に Mac OS メモリマネージャのゾーンに割り当てられます。
  2. どのプールにも初期サイズがあります。
  3. メモリプールは割り込みに対応しています。OT メモリプールからはいつでもメモリを割り当てることができます。しかし、システムタスク時にしかプールを拡大することはできません。このため、割り込み時にメモリを割り当てると、要求を満たすのに十分なメモリがゾーン内にあっても、割り当てに失敗する場合があります。
  4. メモリが足りなくなると、メモリプールはシステムタスク時に Mac OS メモリマネージャからメモリを割り当てます。メモリプールは一定のパーセント単位で追加されていきます。これを増加率と呼びます。増加率は最小増加量を下回ることはありません。
  5. プールが拡大されるのは空きスペースが下限を下回った場合です。上限もあり、これを上回るとプールは縮小を開始します。この機能はカーネルプールだけが利用します。


注意:
Open Transport は ASLM のメモルプール機能を利用していますが、Open Transport の今後のバージョンは ASLM をまったく使わなくなります。その際 Open Transport のメモリプールは Open Transport 自体が実装することになります。



註:
Mac OS SDK CD の ASLM SDK の ASLM Developer's Guide には ASLM メモリプールクラスについてもっと詳しい説明があります。



プールパラメータ

次の表に各種 Open Transport メモリプールの基本的なパラメータを示します。

プールの種別

ゾーン

初期値

増加率

最小増加量

下限

上限

クライエント [1]

アプリ

2K

20%

2K

1K

無限

クライエント [2]

システム

1K

20%

2K

512

無限

共有 [3]

システム

2K

20%

4K

2K+1

無限

共有 [4]

システム

3K

20%

4K

3K+1

無限

カーネル [6]

システム [9]

4K [5]

20%

34K

34K+1

[10]

カーネル [7]

システム [9]

250K

20%

34K

34K+1

[10]

カーネル [8]

システム [9]

16K [5]

20%

34K

34K+1

[10]

ポート

システム

2K

20%

1K

1K+1

無限

註:

  1. この行は、OT アプリケーションライブラリ(名前が「App」で終わるもの)をリンクするクライアントプログラムで、InitLibraryManager を呼び出していないものです。
  2. この行は、OT エクステンションライブラリ(名前が「Extn」で終わるもの)をリンクするクライアントプログラムで、InitLibraryManager を呼び出していないものです。
  3. Open Transport 1.3 以前
  4. Open Transport 2.0 以降
  5. こちらで詳しく解説されています。
  6. Open Transport 1.3 以前
  7. Open Transport 2.0 から 2.5 まで
  8. Open Transport 2.6 以降
  9. OT は、仮想メモリの観点から、カーネルプールのメモリを明示的にホールドします。他のプールのメモリのホールドは保証されません。
  10. OT カーネルプールは下記に示すいくつかの要因にしたがい、拡大または縮小します。


重要:
上記からもわかるように、メモリプールのパラメータは予告なく変更されることがありますので、これらの値に依存してはなりません。



OT メモリの効果的な利用法

このセクションでは、OT メモリ管理システムを効果的に利用するヒントやコツを紹介します。

OT ルーチンとプールの使用法

次の表はメモリ割り当てを行う OT の一般的なルーチンをまとめたものです。それぞれの割り当て量、割り当て先のプールを示します。

ルーチン

プール

概算割当量

OTAllocMem [1], OTAllocMemInContext

クライエント

size パラメータに従う

OTAllocMem [1]

カーネル

size パラメータに従う

OTAlloc

クライエント

ref と fields パラメータに従う

OTAllocSharedClientMem

共有

size パラメータに従う

OTAllocPortMem

ポート

size パラメータに従う

OTOpenEndpoint

クライエント
共有
ポート

16 bytes
150 bytes
1 KB

OTStreamOpen

共有
カーネル

40 バイト
1 KB

OTCreateConfiguration

共有

100 バイト [2]

OTSnd

カーネル

n バイト [3]



重要:
ここに示した量は概算です。使用中のプロトコルの相対的な複雑さや Open Transport のバージョンによっても異なります。プログラムのメモリ使用量を解析する指針として掲載しました。



Notes:

  1. OTAllocMem はリンクするライブラリによって動作が異なります。OT クライアントライブラリ(例えば OpenTransportLib)とリンクすると OTAllocMem はクライアントプールからメモリを割り当てます。OT カーネルライブラリ(OpenTptModuleLib など)とリンクすると OTAllocMem はカーネルプールからメモリを割り当てます。OTAllocMemInContext などの“InContext”で終わる OT ルーチンは勘違いをおこすことはありません。詳しくはテクニカルノート 1173“Understanding Open Transport Asset Tracking”をご覧下さい。
  2. 正確な値は構成の複雑さによります。ここに示した値は OTCreateConfiguration("serial") への単純な呼び出しによる下限の値です。
  3. このメモリが消費されるのは、エンドポイントが送信データをコピーする場合(ACK で放出される)だけです。これがデフォルト設定です。コピーしないで送信する設定であれば、このルーチンはごく少量の管理目的のメモリを割り当てるにすぎません。

MacsBugs でメモリプールを調べる方法

上記の解析は、各ルーチンを繰り返し呼び出しながら各メモリプールへの影響を記録することで得られた帰納的なものです。OT にはメモリプールの利用状況を測定するプログラミングインタフェースはありませんが、MacsBug を使うと簡単に調べることができます。

まず、OT のウェブページ から Open Transport のデバッグバージョンを入手し、インストールパッケージから「OT Debugger Prefs」ファイルを取り出します。

  Open Tpt Debug Installer
    Open Transport Installer
      Open Transport Files
        OT Debugger Prefs

「OT Debugger Prefs」ファイルをあなたのマシンの「MacsBug Preferences」フォルダにコピーして、マシンを再起動します。



重要:
「OT Debugger Prefs」ファイルは、あなたがインストールした OT のバージョンと合致するバージョン番号を持つ OT のデバッグインストーラから取り出すことが重要です。「OT Debugger Prefs」ファイルには、OT ビルドシステムから自動生成された MacsBug テンプレートが含まれ、これは OT のデータ構造体のフィールドレイアウトに適合しています。OT のバージョンが違うとレイアウトも違います。誤ったバージョンの "OT Debugger Prefs" ファイルを使うと、MacsBug で正確な結果は得られません。



「OT Debugger Prefs」ファイルをインストールしたら、各種 OT メモリプールを探して内容表示が可能です。最初に、OT グローバル領域を表示します。68K と PowerPC では、方法が異なります。それぞれ以下のセクションで示します。

PowerPC で OT グローバル領域をダンプする

PowerPC では次のコマンドで OT グローバル領域をダンプします。



>>> dm __gOTGlobal OTGlobal
 Displaying OTGlobal at 0006BDA0
  0006BDA0  fGestaltValue      0000003F 
  0006BDA4  f68KDeferredProc   00000000 
  0006BDA8  fVersion           01308000 
  [... 以下省略 ...]
                             0006BF04  fClientGlobal      
  0006BF04    fClientList      
  0006BF04      fHead          005F1714  
  [... 以下省略 ...]
                             0006BF30    fNativePool      00095320 
  [... 以下省略 ...]
                             0006BF8C  fKernelGlobal      
  0006BF8C    fKernelPool      0039A4A0 
  0006BF90    fKernelPoolMaxSize  #13421772 
  [... 以下省略 ...]
                             0006BFD4    fPortPool        0037AA90  
  [... 以下省略 ...]


OT はそのグローバル領域のアドレスを CFM シンボル、__gOTGlobal としてエクスポートします。上記のコマンドは「OT Debugger Prefs」の OTGlobal テンプレートを使ってそのアドレスをダンプします。メモリの利用状況に関していえば、次の 3 つのフィールドが関係します。

  1. fNativePool -- 共有クライアントプールのアドレス
  2. fKernelPool -- カーネルプールのアドレス
  3. fClientList.fHead -- OT クライアントリストの先頭。リストの最初のクライアントは次のコマンドでダンプできます。

    >>> dm 5f1714 RegisteredClient
     Displaying RegisteredClient at 005F1714
      005F1714  fLink              
      005F1714    fNext            005F15BC  
      005F1718  fProviders         
      005F1718    fHead            005F13D0  
      005F171C  fStreams           
      005F171C    fHead            00000000  
      005F1720  fWhoAmI            070A7134 
      [... 以下省略 ...]


    次のクライアントは fLink.fNex フィールドを辿れば調べることができます。fWhoAmI があなたのアプリケーションヒープを指すのがあなたのアプリケーションです。自分のアプリケーションを見つけたら、TLibraryManager テンプレートを使って fWhoAmI ポインタをダンプして、ASLM との接続情報を表示できます。

    >>> dm 70a7134 TLibraryManager
     Displaying TLibraryManager at 070A7134
      070A7134  __vptr             003873B0 
      070A7138  fPool              070A6780 
      070A713C  fLibraryFile       00000000 
      070A7140  fDefaultPool       070A6780 
      [... 以下省略 ...]


    クライアントプールのアドレスは fDefaultPool フィールドに保持されています。

プールのアドレスがわかるとそれでさまざまなことができます。

  • 次の MacsBug コマンドはプールに関する基本的な情報を表示します。

    >>> dm 70a6780 TMemoryPool
     Displaying TMemoryPool at 070A6780
      070A6780  __vptr             00386F40 
      070A6784  fMemList           070A6770 
      070A6788  fSize              #2408 
      070A678C  fLowMark           #1797 
      070A6790  fHighMark          #4294967295 
      070A6794  fMaxUsed           #352 
      070A6798  fCurFree           #2056 
      070A679C  fZone              06F7CF00 
      070A67A0  fMemType           #1 
      [... 以下省略 ...]


    fSize フィールドはプール内のメモリの総量です。fCurFree はプールに残る空きメモリ量です。

  • dumppool dcmd は、次のようにプール内のメモリブロックのリストを表示します。

    >>> dumppool 70a6780
     Allocated Memory
      ----------------
        70a7000(  #16)   70a7010(  #16)   70a7020( #168) 
        70a70c8(  #64) "!$plnt"
        70a7108(  #40) "!$slst"
        70a7130(  #48) "!$lmgr"
      Free Memory
      -----------
        70a67f8(#2056)




  • dumprawpool dcmd は、次のようにより詳細なリストを表示します。

    >>> dumprawpool 70a6780
     Allocated Memory
      ----------------
      F:   70a67f8(#2056) 
      A:   70a7000(  #16)   70a7010(  #16)   70a7020( #168) 
      A:   70a70c8(  #64) "!$plnt"
      A:   70a7108(  #40) "!$slst"
      A:   70a7130(  #48) "!$lmgr"


68K で OT グローバル領域をダンプする

68K では手順がやや複雑になります。最初に、OT グローバル領域のアドレスを探します。これには次の MacsBug コマンドを使います。



重要:
以下のとおり動作させるためには、OT のデバッグバージョンをインストールして、MacsBug が FetchOTGlobalシンボルを発見できるようにする必要があります。





>>> hx 2800
 The target heap is the System heap at 00002800
>>> il FetchOTGlobal
 Disassembling from FetchOTGlobal
  FetchOTGlobal
     +00000 0015D5E2   LINK       A6,#$0000        | 4E56 0000
     +00004 0015D5E6   MOVE.L     $00092434,D0        | 2039 0009 2434
     +0000A 0015D5EC   UNLK       A6            | 4E5E
     +0000C 0015D5EE   RTS                         | 4E75
     [... 以下省略 ...]


最初のコマンドは現在の MacsBug のターゲットゾーンをシステムヒープに切り替えます。次のコマンドは OT グローバル領域のアドレスを返す関数をディスアセンブルします。FetchOTGlobal + 4 の行で OT グローバル領域のアドレスを D0 レジスタに移しています。ここでは、OT グローバル領域のアドレスはメモリ位置の$00092434 に保存されていることがわかります。次の MacsBug コマンドでこのグローバル領域がダンプできます。



>>> dm 92434^ OTGlobal
 Displaying OTGlobal at 000B5050
  000B5050  fGestaltValue      0000000F 
  000B5054  f68KDeferredProc   00238164 
  000B5058  fVersion           01306007 
  [... 以下省略 ...]


OT グローバル領域をダンプできたら、あとは PowerPC と同じ方法が使えます。

クライアントプールパラメータの制御

上で説明したように、アプリケーションの OT クライアントプールは InitOpenTransport を呼び出したときにアプリケーションヒープに割り当てられます。最初、プールは非常に小さく、必要に応じて増加します。しかしこの動作はいつも必ず最適であるとはかぎりません。特に、アプリケーションで OT メモリ割り当てルーチンだけを使う場合は、それに全アプリケーションヒープを与えるべきです。割り当てルーチンが少しずつアプリケーションヒープを消費する方法は、一度に大きなブロックを与える方法より非効率的です。また、頻繁に割り込み時にメモリを割り当てていると、クライエントのメモリプールが消費されてしまい、割り当てが失敗する可能性が出てきます。

クライントのメモリプールを細かく制御する方法は2つあります

  • OT メモリリザーブを利用する
  • ASLM の API を使って、メモリプールを直接操作する

これらのテクニックは以下に説明します。



重要:
アップルは前者のテクニックを強く推奨します。Open Transport は現在 ASLM のクライエントプールをそのまま利用していますが、今後はそうとも限りません。また、将来のシステムでは ASLM 自体が存在しない可能性があります。



OT メモリリザーブを利用する

アプリケーションゾーンの全体を OT のメモリ割り当てに利用する、もっとも確実な方法は、OT メモリリザーブを利用することです。アプリケーションを起動した時に、大きいメモリブロックを割り当てることによって、メモリリザーブを確保します。その後、メモリが必要になった時は、まず OT を使って割り当てて、それが失敗した場合はメモリリザーブを使います。

このテクニックは OTStreamLogViewer サンプルコードバージョン 1.0.1b1 以降で OTMemoryReserve モジュールで活用されていますので、そのコードを直接利用することができます。



註:
OT メモリを大量に割り当てて、そしてすぐに解除する方法も考えられるかもしれませんが、この手法では期待通りの結果を得られません。メモリを解除した時点で OT のメモリ管理システムはメモリを Mac OS メモリマネージャにメモリをリリースしてしまいます。



ASLM API によるメモリプールパラメータの制御



重要:
このテクニックを利用すると、OT が ASLM を利用していることに依存するだけでなく、ASLM 自体に依存することになってしまいます。このため、アップルはこの方法を推奨しません。





重要:
InitOpenTransportInContext(Carbon または OTClassicContext による実装)を利用する場合はこのテクニックを利用することができません。



クライアントプールをより細かく制御するには ASLM プログラミングインタフェースを使用します。事前に ASLM との接続を初期化しておくと、InitOpenTransport は、その接続(およびそのクライアントプール)を使用し、新しく作成することはしません。ASLM 接続を使うと、クライアントプールのサイズ、割り当てる位置、増加の割合を制御できるようになります。



註:
ASLM でプログラミングを行うには、Mac OS SDK CD の ASLM SDK が必要です。





重要:
68K C/C++コマンドから ASLM を呼び出すには、4 バイト整数を用いてビルドしなければなりません。



このテクニックを使うには、InitOpenTransport の前に InitLibraryManager を呼び出さなければなりません。また、CloseOpenTransport の後に CleanupLibraryManager を呼び出す必要があります。これらのルーチンのプロトタイプは「LibraryManager.h」に定義されています。読者の便宜のため以下に掲載します。



OSErr InitLibraryManager(size_t poolsize, int zoneType, int memType);
void  CleanupLibraryManager(void);


InitLibraryManager へのパラメータで、クライアントプールの初期サイズ(単位はバイト)、クライアントプールの位置(普通は kSystemZone、kApplicZone、kCurrentZone)、クライアントプールのメモリの種類(普通は kNormalMemory、ただしページングが安全でないときにアクセスする場合は kHoldMemory)を指定できます。

次のコードの断片はこのテクニックを示すものです。まずアプリケーションヒープ内に従属ゾーンを確保します(サイズはツールボックス用に多少メモリを残したヒープの残り全部。)次に、InitOpenTransport を呼び出す前に、InitLibraryManager で ASLM に接続します(そして先のゾーンをクライアントプールとします。)



// 重要:
// このコードを利用することで、ASLM に依存してしまいます。 
// このため、アップルでは推奨していません。
                           
                           static OSStatus InitOpenTransportWithMemoryLimit(void)
{
    OSStatus err;
    SInt32 junkTotalFree;
    SInt32 contigFree;
    SInt32 zoneSize;
    Ptr subsidiaryZone;
    THz oldZone;
 
    // まずシステムのメモリマネージャを呼び出し、
    // ヒープ内の最大連続領域を調べる。
    
    PurgeSpace(&junkTotalFree, &contigFree);
    
    zoneSize = contigFree - kBytesReservedForToolboxInApplicationZone;
    
    // そのブロックにメモリを割り当てゾーンを作成する。
    // 続いて ASLM を初期化し、そのゾーン全体(ASLM の
    // オーバーヘッドを除く)を占めるプールの作成を依頼する。
    // 最後に OT を初期化する。
    // すでに ASLM が初期化されているので、OT は ASLM が先の
    // ゾーンに作成したプールで OTAllocMem の要求に応える。

    subsidiaryZone = NewPtr(zoneSize);
    oldZone = GetZone();
 
    // InitZone は現在のゾーンを新しく作成したゾーンに設定するので、
    // 自分で行う必要はない。
            
    InitZone(nil, 16, subsidiaryZone + zoneSize, subsidiaryZone);
    err = InitLibraryManager(zoneSize - 2048, kCurrentZone, kNormalMemory);
    if (err == noErr) {
        err = InitOpenTransport();
        if (err != noErr) {
            CleanupLibraryManager();
        }
    }
    SetZone(oldZone);
 
    return err;
}




重要:
このコードは、DTS サンプルコードの OTStreamLogViewer を簡単にしたものです(エラーチェックを減らしました。)このコードを使う場合はサンプルの元のコードを入手してください。





註:
上記のテクニックは ASLM API を使って行える唯一の方法とはかぎりません。詳細は『ASLM Developer's Guide』を参照してください。





上級編

このセクションでは、OT メモリ管理の関連事項のうち上級編を取り上げます。特に、共有クライアントプールやカーネルプールが時間が経過するにしたがい、拡大、縮小する様子を説明します。ただしその前に、OT メモリシステムの動作を変更する API について学ぶ必要があります。



註:
このセクションは Open Transport アーキテクチャの深い知識を持つ人のための参考用に書きました。理解できなくても気にしないでください。



OTSetMemoryLimits

OTSetMemoryLimits を使うとソフトウェアから OT メモリプールの動作を直接変更することができます。このルーチンのプロトタイプは次のとおりです。



#ifdef __cplusplus
extern "C" {
#endif
 
extern OSStatus OTSetMemoryLimits(size_t growSize, size_t maxSize);
 
#ifdef __cplusplus
}
#endif


growSize パラメータは今すぐ OT にそのサイズまでカーネルプールを拡大することを指示します。このルーチンを呼び出すと、OT はただちにカーネルプールをその値まで増加させます。maxSize パラメータはカーネルプールの新しい最大値です。OT はこの値を超えてカーネルプールを拡大することはありません。

OTSetMemoryLimits は同時に、Open Transport の内部変数 fServerMode を設定します。OTSetMemoryLimits を正の値の growSize で呼び出すと、fServerMode は増加します。growSize がゼロだと fServerMode は減ります。fServerMode がゼロ以外だと、OT は共有クライアントプールやカーネルプールを縮小することはしません。行儀のいいサーバソフトウェアとなるには、起動時に OTSetMemoryLimits で正の growSize を指定し、終了時には growSize にゼロを指定すべきです。

最後に、カーネルプールを 20K 以上増やすと、OTSetMemoryLimits は共有クライアントプールも growSize の値の 10% だけ増やします。

OTSetMemoryLimits は極端にバースト(連続送受信)の多い接続パターンや並行して多数の接続を受け付けるサーバソフトウェアのみが使用するものです。カーネルプールの最大サイズを増やすと、サーバは多数の並行する接続に対応することができます。カーネルプールをすぐに増大させることで(接続があるたびではなく)、サーバは、利用状況に応じてカーネルプールが増大するのを待つことなく、並列の接続でも開始後ただちに受け付けることができます。カーネルプールの縮小を禁止すると、長時間の待機状態の後でも同時に多数の接続に対応できます。

OTSetMemoryLimits はシステムタスク時に呼び出さなければなりません。指定量までカーネルプールを拡大できない場合はエラーが返されます。



重要:
OTSetMemoryLimits は個々の接続の性能を上げることはありません。この関数は数十の接続を並行して持つソフトウェアでしか有効ではありません。DTS はクライアントソフトウェアが OTSetMemoryLimits を呼び出すことはおすすめしません。





註:
OTSetMemoryLimits ルーチンは Open Transport のヘッダファイルにはありません。このルーチンを使う場合は自分でプロトタイプ宣言をしてください。ヘッダに入れていない理由は上記の方針からきています。一般のアプリケーションプログラムはこのルーチンを呼び出すべきではないからです。





註:
OTSetMemoryLimits の前身にあたる OTSetServerMode という関数があります。このルーチンは OTSetMemoryLimits に完全に取り込まれました。



OT メモリプールの拡大

OT は、バイナリ・バックオフ・アルゴリズムを用いてプールを拡大します。まず Mac OS メモリマネージャに 1 個の大きなメモリブロックを要求します。そのサイズのブロックが取得できないと、要求サイズを半分にして再試行します。この動作を要求どおりのプールの拡大に成功するか、ブロックサイズが 10K より少なくなってしまうまで繰り返します。

OT メモリプールの縮小

OT メモリプールは縮小可能です。メモリプールは Mac OS メモリマネージャから割り当てた複数の不連続なメモリブロックからなります。プールを縮小する場合は、Mac OS メモリブロックがそれぞれ空かどうか検査します。空であれば、そのメモリブロックは Mac OS メモリマネージャに返却します。

OT メモリプールは次の場合に縮小されます。

  • クライアントが終了し(CloseOpenTransport を呼び出すか、呼び出さずにアプリケーションが終了する場合)、OT がサーバモードでないと、OT は共有クライアントプールとカーネルプールを減らします。
  • OT がクライアントライブラリをアンロードするとき、共有クライアントプールを減らします。
  • OT がカーネルをアンロードするとき(InitOpenTransport を呼び出しているクライアントが 1 つもなくなったとき)、サーバモードでなければ、カーネルプールを減らします。
  • OT がカーネルユーティリティライブラリをアンロードするとき(InitOpenTransportUtilities を呼び出しているクライアントが 1 つもなくなったとき)、OT はポートプールを減らします。
  • OT はポートスキャナの実行後、ポートプールを減らします。
  • OT は、コンフィグレータのリストを辿り、その OTSetupConfigurator または OTStartupConfigurator エントリポイントを呼び出した後ただちに、共有クライアントプールを減らします。

カーネルプールに関するその他の詳細事項

OT はカーネルプールサイズの上限に固定の限界値を設定しています。クライアントはこの限界値を OTSetMemoryLimits ルーチンで設定できます。ここで疑問がわきます。限界値の初期値はなんでしょう。インストールの直後には、OT はこれをマシンの物理メモリ(gestaltPhysicalRAMSize で調べる)の 10% に設定します。この値は、ネットワークソフトウェアに十分なバッファ空間を与えつつ、OT がユーザの全メモリを消費しないようバランスを取った結果です。

カーネルを最初にロードすると、OT は上記の初期値でカーネルプールを作成します。しかし、カーネルがロードするたびに(最初のときも含めて)、OT はロードを完了する前に少なくとも 96KB だけカーネルプールを増加させます。これは、カーネルがアンロードされているときはカーネルプールを小さくし、ロードの際にはすばやく増加させるためです。



要約

Open Transport は信頼性のある柔軟で割り込みに対応したメモリ管理システムです。動作原理を理解することで、陥りがちな失敗を避けながら、しかも割り込み時にメモリを割り当てるコードを書くことができるようになります。



参考文献

変更履歴

[1998年5月11日]

最初にリリース

[2001年1月9日]

ASLM への依存について警告し、ASLM の利用を避けるような手法を紹介しました。プールパラメータに 1998 年以降の OT リリースを追加しました。