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

Technote 1184

FCBs, Now and Forever


目次

はじめに

FCB の前史

FCB のはじまり

System 7.0 時代

System 7.5 時代

Mac OS 8.1 時代

Mac OS 9.0 時代

要約

Mac OS 9.0 は FCB (File Control Block) テーブルのフォーマットを大幅に変更します。このテクニカルノートでは、まず FCB のオリジナルフォーマットについて説明し、さらに、長年にわたって FCB テーブルの使い方がどのように変遷してきたか、また互換性のある方法で FCB 情報にアクセスするにはどうすればいいか、といった問題について説明します。

すべての Mac OS デベロッパは、 「現実に即した提案」 のセクションを読んで、開発中のソフトウェアが Mac OS 9.0 およびそれ以降と互換性があることを確認してください。

ソフトウェアに Mac OS 9.0 との互換性がない (特に、システムエラー 119 の原因になります) 場合は、 「FCB の問題のデバッグ」 のセクションを読んでください。.

このテクニカルノートのその他のセクションでは、Mac OS 考古学の愛好者にとって興味深いであろう背景資料を明らかにします。


はじめに

Mac OS 9.0 以前、Macintosh で同時にオープンできるファイルの数 (FCB) は 348 に制限されていました。この制限がユーザとデベロッパの双方にとって問題であることは明らかだったため、Mac OS 9.0 の設計目標の 1 つはこの制限値を大幅に増加させることでした。しかし、あらゆるものにその代償が伴います。FCB の数を増加させることの代償は「互換性」という問題でした。Mac OS は HFS の導入 (1986 年) 以来、同一の FCB テーブルフォーマットを使用してきました。また、多くのデベロッパがこのフォーマットを頼りに成長してきました (それがいいことかどうかは別の問題として)。

注意:
「Fork Control Block」という用語は、伝統的に使用されてきた「File Control Block」という用語よりも技術的には正確であるといえます。混乱を避けるため、このテクニカルノートでは原則としてつねに「FCB」という略語を使用します。

このテクニカルノートでは、長年にわたって FCB テーブルフォーマットに加えられてきた変更と、これらの変更がデベロッパにもたらした影響について説明します。FCB の全史はかなり複雑であるため、このテクニカルノートでは、どちらかといえば古いタイプのコードをかかえているデベロッパ向けにいくつかの現実に即した提案から話を始めることにします。

現実に即した提案

Mac OS 9.0 は FCB テーブルにとって究極の進化ではありません。Apple では、システムの進化に合わせて今後も FCB テーブルに変更を加えていく予定です。このため、今すぐ自分の書いたコードを確認して、将来にわたる互換性を維持できるように努力することが肝要です。

特にチェックすべき項目はファイル参照番号の使い方です。ファイル参照番号は、正の SInt16 型の値と定義されています。特別なファイル参照番号というものは存在しません。2 という番号がシステムファイルのファイル参照番号であるということは保証されていません。また、(refNum mod 4) = 2 (Mac OS 9 以前は (refNum mod 94) = 2) という等式も保証されていません。

注意:
0 という番号は、nil ファイル参照番号と nil デバイス参照番号の両方として最適です。

アプリケーションレベルのソフトウェア (アプリケーション、共有ライブラリなど) にとって、将来的な互換性に向けた最善の道筋は Carbonです。Carbon プログラミングインタフェースは、特に将来的なシステムでサポートされることを前提に設計されています。Carbon に対応したプログラミングを行っていれば、将来的にローレベルの File Manager の変更から影響を受けることはありません。

特に、アプリケーションレベルのコードから FCB 情報にアクセスする必要がある場合は、File Manager ルーチンの FSGetForkCBInfo (または、そのパラメータブロックバリアントの PBGetForkCBInfoSync と PBGetForkCBInfoAsync、あるいは Mac OS 9.0 以前のシステムでは PBGetFCBInfoSync と PBGetFCBInfoAsync)を使用してください

ただし、File Manager を呼び出して FCB 情報を取得できない状況もあります。たとえば、File System Manager (FSM) プラグインを書いている場合や、システム機能拡張を書いていて、そのコードが File Manager パッチのコンテキスト内で実行される場合などです。これらの状況では、FCB に直接的にアクセスする必要があります (つまり、File Manager リクエストをキューに格納しないということです)。

FCB に直接的にアクセスする必要があって、FSM が使用可能な場合は、 FSM アクセッサルーチンを使用してください。これらのルーチンについては、このテクニカルノートの後半で説明します。

FCB テーブルへの直接的なアクセスが容認される唯一のケースは、FCB への直接アクセスが必要で、しかも FSM が存在しないときです。

FCB の問題のデバッグ

開発したソフトウェアが Mac OS 9.0 上で正常に動作しなくて、FCB テーブルへの依存がその原因であると考えられる場合は、問題のデバッグに使用できる多くの方法が存在します。このセクションでは、ソースコードを検索して FCB 関連のバグを発見する方法と、この問題のデバッグに使用できるいくつかのランタイムデバッグ手法について説明します。

ソースコードの検索

ソフトウェアが FCB テーブルのフォーマットに依存しているかどうかを一目で判断する方法は、それを Mac OS 9.0 で実行してみることです。しかし、このトリッキーな方法はソース全体にわたって実行しなければ意味がありません。FCB テーブルへの依存は、テストでは実行されないような、まれにしか使用されない機能の中に隠れていることもあります。テストに代わる最善の代替案は、ソースコードを検索して FCB への参照を見つけ出すことです。

PowerPC ソフトウェアの場合は、Carbon Dater ツール (Carbon Web サイト からダウンロードできます). を介してプログラムを実行することから始めてください。これにより、FCB テーブルローメモリアクセッサルーチン (LMGetFCBSPtr、LMSetFCBSPtr、LMGetFSFCBLen、および LMSetFSFCBLen) と、ローメモリアクセスを指示する PowerPC コードのシーケンスへの参照にフラグを立てることができます。しかし残念なことに、Carbon Dater はすべてのローメモリアクセスを検出できないため、ソースコードをテキストベースでも検索する必要があります。

Carbon Dater は 68K ソフトウェアには使用できないため、ソースコードで FCB テーブルへの直接アクセスを指示するいくつかの (あまり一般的ではない) 文字列を検索するのが最善の方法といえます。たとえば、次のような文字列を検索します。

  • 「FCBSPtr」と「FSFCBLen」 - 主要なローメモリグローバルの正式名。
  • 「34E」と「3F6」 - 16 進で表記した上述のもの。
  • 「846」と「1014」 - 10 進で表記した上述のもの。

すべてのソフトウェアのソースがない場合は、68K コードリソースで $034E と $03F6 を検索してもかまいません。これら両方の値は 68K 命令としてはまれなもので、これらの値が検出された場合は、その周囲のコードを逆アセンブルして、それが FCB テーブルへのアクセスであるかどうかを確認する価値があります。

システムエラー 119

ソフトウェアを実行したときに、システムエラー dsMustUseFCBAccessors 119 によるクラッシュが発生する場合、このことは、PowerPC コードが FCB テーブルに直接的にアクセスしていることの明らかな証拠といえます。詳細については、後述の「PowerPC コードとローメモリアクセッサ」を参照してください。

悲惨なクラッシュ

Mac OS 9.0 上で実行したアプリケーションが例外アクセス (またはバスエラー) でクラッシュする場合は、プログラムのステータスを調べて、問題が FCB に関連しているかどうかを判断することができます。プロセッサのレジスタまたはローカル変数の中に以下のいずれかが存在する場合は、FCB 関連のトラブルが発生しています。

  • ローメモリグローバル FCBSPtr ($034e) によって参照される 32KB ポインタブロックへのポインタ。
  • $68F168F1 という値。この値は、いずれかの方向に 16 ビットだけシフトしている可能性もあります。これはバスエラーの値で、File Manager はこの値を使って、フェイク FCB テーブルに未使用のエントリを書き込みます。詳細については、「68K コードとローメモリ」を参照してください。.
  • VCB のアドレスである値 (MacsBug の vol コマンドを使用すると、VCB リストを表示できます)。この値は、いずれかの方向に 16 ビットだけシフトしている可能性もあります。詳細については、「68K コードとローメモリ」を参照してください。

ページの先頭に戻る

FCB の前史

現在われわれが知っている FCB は HFS の一部として導入されました。HFS は、128K ROM またはそれ以降のすべてのコンピュータ (1986 年発売の Macintosh Plus 以降のすべてのコンピュータ) に組み込まれています。また、64K ROM コンピュータ (Macintosh 128 および 512) では機能拡張として使用されていました。

いくつかの例外的なケースを除き、このテクニカルノートでは、128K ROM システムまたはそれ以降に対応したプログラミングを行うことが前提になっています。64K ROM マシンでは System 7.0 がサポートされていないため、この前提は正当なものといえます。さらに、現在の開発環境では、64K ROM に対応した開発はサポートされていません。要するに、64K ROM に対応した開発を行っている場合、われわれの共感は得られても、サポートは得られないということです。


ページの先頭に戻る

FCB のはじまり

このセクションでは、クラシック FCB テーブルフォーマットについて説明します。このフォーマットは、HFS ファイルシステムとともに導入され、Mac OS 9.0 のリリースとともに現役を退きました。また、このフォーマットに対するいくつかの制限についても論じます。

クラシック FCB テーブル

クラシック FCB テーブルが導入されたとき、HFS は単純なテーブルを使って FCB を格納していました。このテーブルは、システムヒープ内のポインタブロックとして保持され、ローメモリグローバル FCBSPtr ($34E) によってポイントされます。このテーブルは、2 バイトのヘッダ (この中にはポインタブロックのサイズが含まれます) と、それに続く FCB の配列から構成され、これらのヘッダと配列はそれぞれ固定長のサイズを持ちます。このサイズは、別のローメモリグローバルである FSFCBLen ($3F6) によって決定され、HFS が導入されたとき、このローメモリグローバルには 94 という値が含まれていました。

次に、クラシック FCB テーブルのフォーマットを示します。

gif#1

ファイル参照番号は、このテーブルの対応する FCB へのオフセットです。第 N 番目のファイルに対するファイル参照番号は 2 + (N - 1) * FSFCBLen で、この値は 2、96、190、284、... などとなります。

FCB テーブルの設計上の制限

このような FCB テーブルの基本構造は、FCB の数、つまりは同時にオープンできるファイルの数に対する制限を暗示しています。オリジナル Macintosh (メモリに極端な制約がありました) では、10 個の FCB を含むテーブルを作成していました。この数は、ブートブロック (BootBlkHdr) の bbCntFCBs フィールドから導き出された値でした。Macintosh Plus が登場したとき、インストールされているメモリに合わせて、システムはこの数を自動的に拡大しました。コンピュータに 1MB またはそれ以上のメモリが搭載されていると、システムは bbCntFCBs * 4 のエントリを含む FCB テーブルを作成します。その結果、大部分の System 6 コンピュータでは、40 のエントリを含む FCB テーブルが作成されていました。

System 6 時代も終わりに近づいたころ、この制限が多くのユーザにとって問題であることが明らかになりました。この問題を解決するためには 2 つの方法が存在しました。まず 1 つは、ディスクエディタ (伝説的な FEdit など) を使ってブートブロックを編集し、制限値を増加させるという方法でした。またもう 1 つは、システム起動時に FCB テーブルをその最大サイズまで拡大する「Up Your FCBs」システム機能拡張をインストールするという方法でした。

クラシック FCB テーブルの最大サイズは 32KB で、これは主として、ファイル参照番号が 16 ビットの符号付きオフセットであることに起因しています。その結果、(32768 - 2) div FSFCBLen で計算される FCB の最大数は、94 バイトの標準的な FCB サイズの場合で 348 ということになります。

注意:
『Inside Macintosh: Files』では、クラシック FCB テーブルで許可されるオープンファイルの最大数を 342 と記載していますが、これは誤りです。最大は 348 です。

注意:
FCB の最大数は、アプリケーションがオープンできるファイルの最大数とは異なります。システムでは、これらの FCB の一部を内部的な目的に使用しています。このような FCB の使い方はファイルシステムのインプリメンテーションを行う上で避けることのできない問題ですが (HFS カタログやエクステントファイルに使用する FCB など)、その他のファイルはシステムソフトウェアによって明示的にオープンされます (システムファイルやさまざまな共有ライブラリなど)。モダンシステムでは多数のオープンファイルを管理しており、アプリケーションソフトウェアで使用可能な FCB の数はきびしく制限されています。たとえば、Mac OS 8.6 の簡易インストールを行う場合、Finder が表示されるまでに、すでに 100 個のファイルがオープンされています。

互換性に関する注意

クラシック FCB テーブルはパブリックなデータ構造体ではありませんでした。While the format is well known擁t is described in Technote 1089, 「Technote 1089, HFS について (改訂版)」に記載されているフォーマットはよく知られていますが、これらの説明は、このフォーマットへの依存が将来的に互換性の問題を引き起こす可能性があるという警告を含んでいます。

ただし、FSFCBLen ローメモリグローバルにはドキュメント化された使い方、すなわちシステムで HFS が使用可能であるかどうかを判断するという使い方があります。このメカニズムは、「Technote FL_35, Determining Which File System Is Active」で説明されています。この手法では、HFS が使用可能な場合に FSFCBLen が正の数であり、そうでない場合には負の数であることが要求されます。その符号をテストすること以外に FSFCBLen についてドキュメント化された使い方は存在しません。


ページの先頭に戻る

System 7.0 時代

System 7.0 は、FCB に関連するいくつかの新しいファイルシステム機能を導入しました。このセクションでは、それらの機能について説明します。なお、System 7 と Mac OS 8 のすべてのバージョンではクラシック FCB テーブルフォーマットを使用し、このフォーマットから多数のプロパティを継承しています。

パラレル FCB テーブル

System 7.0 は、プロセスごとに FCB の使用状況を追跡する最初のシステムでした。あるプロセスがファイルをオープンするとき、対応する FCB はそのプロセスに属するものとしてタグをつけられます。そのプロセスが不意に終了してしまうと、Process Manager はそのプロセスによって所有されていたすべての FCB を自動的にクローズします。

残念なことに、クラシック FCB には所有プロセスの ProcessSerialNumber (PSN) を格納するための領域がありませんでした。FCB を増大させることは可能でしたが (FSFCBLen を変更して)、これが原因で 2 つの重要な不都合が発生していました。

  1. クラシック FCB テーブルのサイズは 32KB に制限されているため、FCB のサイズを大きくすると、FCB の最大数が減少してしまう。
  2. FCB のサイズを大きくすると、ハードコードされた sizeof(FCBRec) をコードに挿入しているデベロッパに互換性の問題が発生する可能性がある 。(bad developers!).

これに代わって、System 7 はパラレル FCB テーブルという概念を導入しました。このテーブルは、ファイルをオープンしたプロセスの PSN を格納し、プロセスが終了したときに、そのプロセスによってオープンされたままになっているファイルをすべてクローズするために使用されました。

重要:
パラレル FCB テーブルはサードパーティのデベロッパ向けにドキュメント化されたことはなく、Mac OS 9.0 では削除されてしまいました。ここでは、単なる情報としてだけパラレル FCB テーブルについて説明しているまでで、このテーブルまたはそのインプリメンテーションの詳細に依存しないように注意してください。

Process Manager は、同期的にオープンされているファイルを追跡するだけです。Process Manager では、非同期的にオープンされているファイル (たとえば、PBHOpenDFAsync を使って) を追跡できません。なぜなら、これらの呼び出しは割り込み時に実行される可能性がありますが、割り込み時に所有プロセスを簡単に判断する方法は存在しないためです。

動的に拡大する FCB テーブル

System 7.0 はさらに、FCB テーブルを動的に拡大するメカニズムも導入しました。FCB テーブルがいっぱいになっているときにプログラムがファイルをオープンしようとすると、システムは tmfoErr (-42) を返します。System 7.0 でこのような状況が発生すると、システムはエラーを捕捉し、FCB テーブルの拡大を試みた後、ファイルオープンを再試行します。システムが FCB テーブルを拡大できるのは、次の条件が満たされているときだけです。

  • ファイルをオープンするリクエストが同期的に実行された。非同期リクエスト (たとえば、PBHOpenDFAsync を使った) は潜在的に割り込み時に実行される可能性があり、割り込み時に Memory Manager を呼び出して FCB テーブルを拡大するのは不正な処理です。
  • システムヒープに新しいテーブルを格納するための十分な領域がある。
  • テーブルが FCB の最大値である 348 よりも小さい。

FCB テーブルが完全にいっぱいになっていなければ、ファイルを同期的にオープンするときに tmfoErr エラーが返されることはまずありませんが、このような制限があるため、System 7.0 またはそれ以上でも tmfoErr エラーが返される可能性があります。


ページの先頭に戻る

System 7.5 時代

System 7.5は、システムファイルの一部として File System Manager (FSM) を組み込んだ最初のシステムでした。FSM は、FCB テーブルフォーマットの知識を前提とすることなく、FCB へのアクセスを可能にするいくつかのルーチンを提供します。

たとえば、次のような 4 つの FCB アクセッサ関数です。

  1. UTResolveFCB - ファイル参照番号を FCB にマップする。
  2. UTIndexFCB - あるボリューム上のオープン FCB にインデックスを設定する。
  3. UTLocateFCB - ファイル番号とボリュームによって FCB を検索する。
  4. UTLocateNextFCB - ファイル番号 (または名前) とボリュームによってその他の FCB を検索する (UTLocateFCB を使用した後で)。

これらのルーチンは、File System Manager SDK の一部であるFile System Manager SDKの中でドキュメント化されています。

重要:
これらの FCB アクセッサルーチンは、Mac OS 8.5 より前の InterfaceLib の中には存在しません。DTS サンプルコード MoreIsBetterの MoreInterfaceLib モジュールには、以前のシステムで CFM コードからこれらのルーチンを呼び出すための Mixed Mode グルーが含まれています。

重要:
Mac OS 9.0 では、UTIndexFCB はイテレータコントロールブロックも返します。オープンファイルにのみ関心がある場合は、後述の手法を使って、これらのイテレータコントロールブロックを明示的にスキップする必要があります。

注意:
これらの FCB アクセッサルーチンは Carbon の一部ではありません。Carbon コードには、FCB への直接アクセスは含まれていません。詳細については、「現実に即した提案」のセクションを参照してください。

これらの FCB アクセッサルーチンは、もともと FSM プラグイン (およびその他の外部ファイルシステム) による使用を想定していましたが、他のコードの中でこれらのルーチンを使っても何ら問題はありません。ただし、これらのルーチンを使用する前に「現実に即した提案」のセクションを読んで、File Manager ルーチン (たとえば、FSGetForkCBInfo) を使用する方がむしろ賢明ではないかどうかを判断してください。

次のコードを使用すると、これらのルーチンのアベイラビリティをテストできます。

static Boolean HasFCBAccessors(void)
{
    Boolean result;
    long    response;
                  
    result = false;
    
    // FSM がインストールされていることを確認する
    
    if ( Gestalt(gestaltFSAttr, &response) == noErr ) {
        if ( (response & (1L << gestaltHasFileSystemManager)) != 0 ) {
                  
            // FSM 1.2 はドキュメント化されている API をサポートする
            // 最初のバージョンであるため、バージョンをチェックする
            
            if ( Gestalt(gestaltFSMVersion, &response) == noErr ) {
                  
                // FSM 1.2 またはそれ以上であることを確認する
                
                if ( (unsigned long)response >= 0x0120) {
                    result = true;
                }
            }
        }
    }
    return result;
}


ページの先頭に戻る

Mac OS 8.1 時代

Mac OS 8.1 は、新しい組み込みボリュームフォーマットであるHFS Plus.を導入しました。Mac OS 8.1 では、File Manager の内部にかなり大きな変更が加えられましたが、FCB テーブルの変更はごくわずかでした。

HFS Plus はそのエクステント情報を格納するためにより大きな領域を必要とするため、最も重要な変更が要求されました。クラシック FCB テーブル は FCB の fcbExtRec の中にファイルの先頭から 3 つのエクステントを格納します。このとき、それぞれのエクステントは 16 ビットのアロケーションブロック番号で、16 ビットの長さを持ちます。一方、HFS Plus ではファイルの先頭から 8 つのエクステントを格納する必要があり、それぞれのエクステントは 32 ビットのアロケーションブロック番号で、32 ビットの長さを持ちます。このため、新しいエクステントデータがクラシック FCB に収まりきらないことは明らかでした。

この問題の解決に採用された方法は、HFS Plus ボリューム上のファイルに対するエクステントデータをパラレル FCB テーブルに格納し、FCB の fcbExtRec フィールドは未使用のまま (しかもゼロに設定して) 残すというものでした。クラシック FCB テーブルをほとんど変更しないまま残すため、これは非常に互換性の高い解決方法でした。破綻するのは fcbExtRec に依存するソフトウェアだけですが、このようなソフトウェアは、新しいより大きなアロケーションブロック番号により、いずれは破綻することになります。


ページの先頭に戻る

Mac OS 9.0 時代

このセクションでは、Mac OS 9.0 File Manager の FCB に関連する機能について説明します。また、Mac OS 9.0 で加えられた変更の背後にある合理的な根拠も示します。さらに、オープンファイル数に対する新しい制限が 8,169 になった理由についても説明します。

Design Goals

Mac OS 9.0 には、次のような File Manager に対する大幅な拡張が組み込まれています。

  • 長いファイル名 (255 Unicode 文字) やサイズの大きなファイル (> 2 GB) などの HFS Plus の機能にアクセスするための新しいプログラミングインタフェース
  • オープンファイル数の制限を 348 から 8169 に拡大する新しい FCB テーブルフォーマット
  • 大部分の File Manager 呼び出しをプリエンプティブタスク (MP タスク) から実行する機能

拡張された File Manager に対する設計条件の 1 つは、これまでにドキュメント化されているプログラミングインタフェースを使用しているソフトウェアを正常に動作させつつ、これらの新しい機能をインプリメントするということでした。オープンファイルの最大数を増加させるためには FCB テーブルフォーマットに変更を加える必要がありますが、このフォーマットはデベロッパが依存できるものとしてこれまでドキュメント化されていませんでした。

注意:
FCB テーブルのフォーマットに依存することの危険性はこれまで繰り返し警告されてきました。

  • 『Inside Macintosh II』 (127 ページ)「警告: ファイルコントロールブロックのサイズと構造は Macintosh システムソフトウェアの将来のバージョンで変更される可能性があります」
  • 『Inside Macintosh IV』 (181 ページ)「警告: ファイルコントロールブロックのサイズと構造は Macintosh システムソフトウェアの将来のバージョンで変更される可能性があります」
  • 『Inside Macintosh V』 (386 ページ)「ファイルコントロールブロック (FCB)、ボリュームコントロールブロック (VCB) などのシステムデータ構造体をメモリ内で直接的に検査または操作しないでください。File Manager 呼び出しを使って、FCB および VCB 情報にアクセスします
  • 『Inside Macintosh: Files』, (2-81 ページ)「注意: ファイルコントロールブロックのサイズと構造は Macintosh システムソフトウェアの将来のバージョンで変更される可能性があります。安全のため、File Manager 関数の PBGetFCBInfo を呼び出して、オープンファイルに割り当てられている FCB の情報を取得してください」
  • 「Technote 1089, HFS について (改訂版)」 「次の例は、説明を目的としてあげられているだけです。この例をそのまま使用すると、将来のシステムソフトウェアとの間で互換性の問題が発生する可能性があります」

Gestalt

Mac OS 9.0 では、システムが新しい FCB テーブルフォーマットを使用していることと、FCBSPtr、FSFCBLen、またはそれらのローメモリアクセッサルーチン (LMGetFSFCBLen を除く) に依存できないことを示す新しい Gestalt ビットが定義されています。この Gestalt ビットは gestaltFSAttr の gestaltMustUseFCBAccessors (ビット 13) です。原則として、FCB アクセッサを使用すべきかどうかを判断するためにこの Gestalt ビットを使用しないでください。むしろ、使用可能な場合は、常に FCB アクセッサを使用するようにしてください。

大きな変更

Mac OS 9.0 では、FCB 情報がプライベートテーブルに格納されるようになりました。ただし、このテーブルのフォーマットはデベロッパ向けにドキュメント化されていません。

これまでパラレル FCB テーブルに格納されていた情報は拡張 FCB の中にまとめられました。拡張 FCB は、FSM.h ファイルの中で ForkControlBlock 型によって定義されています。

また、Mac OS 9.0 は FCB テーブル内にイテレータコントロールブロックを格納します。詳細については、「イテレータコントロールブロック」 を参照してください。

FCB への直接アクセスを必要とするデベロッパはFSM アクセッサを使用する必要があります。また、Mac OS 9.0 にはさらにいくつかの FSM アクセッサが導入されました。詳細については、「新しい FSM アクセッサ」 のセクションを参照してください。

68K コードとローメモリ

FCB テーブルフォーマットに大量の変更が加えられたことを考えれば、クラシック FCB テーブルフォーマットに関連するローメモリグローバル (前述したFCBSPtr と FSFCBLen) がもはや何の意味も持たないことを明らかです。Apple ではもともと、これらの変数に、アクセスするとバスエラーを引き起こすような値を設定しようと考えていましたが、さまざまな検討を加えた結果、このようなポリシーに落ちつきました。

残念ながら、Apple が提供する GetVRefNum のグルーはクラシック FCB テーブルフォーマットに依存しています。このグルーは多くの 68K アプリケーションに静的にリンクされているため、Apple ではクラシック FCB テーブルを完全に排除できませんでした。むしろ、このグルーが正常に動作し続けるように、フェイク FCB テーブルが注意深く組み立てられています。

注意:
Apple が提供する GetVRefNum のグルーは、さまざまな開発環境のさまざまなライブラリの中に組み込まれています。

  • MPW は「Interface.o」の中に GetVRefNum を含んでいます。
  • CodeWarrior は「MacOS.lib」の中に GetVRefNum を含んでいます。
  • Think C および Symantec C は「MacTraps」の中に GetVRefNum を含んでいます。
  • Think Pascal は「Interface.Lib」の中に GetVRefNum を含んでいます。

フェイク FCB テーブルはこれまで同様、FCBSPtr によってポイントされますが、FSFCBLen は 4 に設定されています。テーブルは、システム上に実際に存在する各 FCB に対応した複数のフェイク FCB から構成されています。フェイク FCB は FSFCBLen (4 バイト) によって配置され、それぞれは、フェイク FCB 内への 20 ($14) バイトのオフセット (FSFCBLen によってレポートされる、FCB の境界を $10 バイト超えた位置) に有効な fcbVPtr を含んでいます。次の図はこのレイアウトを図式化したものです

tn1184.2.gif

このレイアウトにより、GetVRefNum は、すべてフェイク FCB テーブルを使用して、FCB テーブルの検索、ファイル参照番号が有効であるかどうかのチェック、および FCB の fcbVPtr フィールドの検索を行うことができるようになります。

注意:
次に、Interface.o の GetVRefNum グルーを逆アセンブルした結果を示します。

; function GetVRefNum(fileRefNum: integer; VAR vRefNum: integer): OSErr;
                           
GetVRefNum
        MOVEA.L    (A7)+,A1         ; リターンアドレスをポップ
        MOVEQ      #$00,D1          ; fileRefNum を取得 (ゼロ拡張)
        MOVE.W     $0004(A7),D1     ;
        MOVEA.L    FCBSPtr,A0       ; FCB テーブルポインタと
        MOVE.W     FSFCBLen,D0      ; FCB サイズを取得
        BMI.S      NoHFS            ; 負の数なら HFS 以前
@HFS
        DIVU.W     D0,D1            ; fileRefNum を FSFCBLen で除算
        BRA.S      DoneDivision
@NoHFS
        DIVU.W     #$005E,D1        ; fileRefNum を HFS 以前の
                                    ; FCB で除算
@DoneDivision
        SWAP       D1               ; fileRefNum mod FCB サイズを取得
        SUBQ.W     #$2,D1           ; fileRefNum mod FCB サイズが
        BNE.S      BadResult        ; 2 でなければ、エラーアウト
                           
        MOVE.W     $0004(A7),D0     ; fileRefNum が FCB テーブルの
        CMP.W      (A0),D0          ; サイズよりも大きい場合は、
        BCC.S      @BadResult       ; エラーを返す
        
        MOVEA.L    $14(A0,D0.W),A0  ; 適切な FCB、VCB へのポイントから
                                    ; fcbVPtr を取り出す
        MOVE.W     $004E(A0),D0     ; VCB から vcbVRefNum を取り出す
        MOVEQ      #$00,D1          ; noErr
        BRA.S      @GoodResult
                           
@BadResult
        MOVEQ      #$00,D0
        MOVE.W     #$FFCD,D1        ; rfNumErr
                           
@GoodResult
        MOVEA.L    (A7),A0          ; D0 を vRefNum の中におく
        MOVE.W     D0,(A0)          ;
        ADDQ.W     #$6,A7           ; パラメータをポップ
        MOVE.W     D1,(A7)          ; D1 を関数の結果の中におく
        JMP        (A1)             ; 呼び出し元に制御を戻す

注意:
フェイク FCB テーブルは、オープンファイルの数に対する 8169 という制限の根拠になっています。以前と同様に、フェイクテーブルのサイズは 32KB に制限されています。SInt16 をラップするために FCB テーブル内を移動するコードが生成される可能性があるため、最後の 94 バイトを超えた位置に FCB が配置されることはありません。したがって、フェイク FCB で使用可能な数は、(32768 - 94 - 2) div 4 + 1、つまり 8169 になります。

PowerPC コードとローメモリアクセッサ

PowerPC コードのケースはいくらか単純です。PowerPC コードの場合、GetVRefNum のインプリメンテーションはシステムソフトウェアの一部であるため、新しい FCB テーブルフォーマットに対応するように修正されました。

一方、FCBSPtr および FSFCBLen に対するローメモリアクセッサルーチンはより興味深い問題を提起しました。これらのルーチンは FCB テーブルのフォーマットに依存していないため、デベロッパは理論的にはこれらのルーチンを使用していないはずでした。しかし現実には、驚くほど多くのアプリケーションがこれらのルーチンを使用していることが明らかになり、Apple ではこれらのルーチンの動作を再検討せざるをえなくなりました。

最終的な決定は次のとおりです。

  • LMGetFCBSPtr、LMSetFCBSPtr、および LMSetFSFCBLen はすべて dsMustUseFCBAccessors (119) システムエラーを発生させる。
  • LMGetFSFCBLen はこれまで同様 FSFCBLen の値 (現在は 4) を返す。

次に、このような変更の根拠を示します。

  • FCB テーブルのフォーマット (FCBSPtr によってポイントされる) は根本的に変更されました。このため、このフォーマットに依存するソフトウェアは正常に動作しなくなります。ソフトウェアが正常に動作しなくなるのであれば、ソフトウェアの動作をできるだけ早く停止させるのが得策といえます。これにより、古いソフトウェアによって発生する可能性のあるデータの消失を防ぐことができます。
  • 明確なシステムエラー番号を使用することで、テクニカルサポート担当者がこの問題を迅速に診断できるようになります。
  • FSFCBLen にはドキュメント化された使用法(前述したように、HFS が存在するかどうかをテストします) があるため、この目的で使用する FSFCBLen は今後も正常に動作し続けます。

イテレータコントロールブロック

Mac OS 9.0 の File Manager は「イテレータ」と呼ばれる新しいメカニズムを導入し、ディレクトリ内またはボリューム上にあるすべての項目を検出できるようになりました。イテレータは、特定のバルクカタログオペレーションのステータスを保持するために使用される絶対オブジェクトです。FSIterator データ型によって記述されるイテレータは、FSOpenIterator によって作成され、FSCloseIterator によって廃棄されます。

トラディショナル Mac OS では、FSIterator のステータスは FCB テーブル内の イテレータコントロールブロック (of type IteratorControlBlock) の中に保持されます。イテレータコントロールブロックは FCB に似ていますが、オープンファイルではなく FSIterator のステータスを保持する点が異なります。

FSM アクセッサを使用するソフトウェアでは、このようなイテレータコントロールブロックの取り扱いに十分注意する必要があり、これらを FCB として単純に取り扱うことだけは絶対に避けなければなりません。FCB の moreFlags フィールドに含まれる fcbIteratorBit をテストすることで、IteratorControlBlock と ForkControlBlock を明確に識別することができます。

重要:
FCB の moreFlags フィールドは Mac OS 9.0 より前には存在しません。Gestaltを使って、イテレータコントロールブロックのテストを条件づけてください。

新しい FSM アクセッサ

Mac OS 9.0 は、前述したルーチンを補足する多数の新しい FSM ユーティリティルーチンを導入しました。次のようなルーチンが導入されました。

  • UTGetForkControlBlockSize - FCB のサイズを返します。LMGetFSFCBLen はもはや使用できず、システムの進化とともに FCB もさらに拡張されることが予想されるため、このルーチンが必要です。
  • UTResolveFileRefNum - 指定した FCB に対応するファイル参照番号を返します。
  • UTCheckFCB - FCBRecPtr が有効な FCB をポイントしているかどうかを検証できます。
  • UTCheckForkPermissions - UTCheckPermission に代わるルーチンで、使い方がいくらか簡単になっています。

また、FCB は検索リストの中に置かれ、オープンファイルの検索が高速化されました。次のルーチンを使用することで、外部ファイルシステムもこのような検索リストによる処理の高速化の恩恵を享受できるようになります。

  • UTAddFCBToSearchList
  • UTRemoveFCBFromSearchList
  • UTLocateFCBInSearchList

このようなルーチンはすべて、今後、「Guide to the File System Manager」の改訂版の中でドキュメント化される予定です。

注意:
これらの FCB アクセッサルーチンは Carbon の一部ではありません。Carbon コードには、FCB への直接アクセスは含まれていません。詳細については、Concrete Advice「現実に即した提案」 のセクションを参照してください。


ページの先頭に戻る

要約

FCB テーブルのフォーマットはデベロッパへの説明を目的としてこれまで何度かドキュメント化されましたが、このフォーマットの変遷が中断することはこれまで一度としてありませんでした。Mac OS 9.0 でもこのテーブルのフォーマットは変更され、主としてシステム上のオープンファイルの最大数が増加しました。Apple では、既存のドキュメント化されているすべてのプログラミングインタフェースが正常に動作し続けるということを前提にこの変更を実現しました。さらに、既存の FSM アクセッサ (System 7.5 で導入された) により、必要な場合は FCB への直接アクセスが可能です。ただし Apple では、FCB への直接アクセスをできるだけ避け、むしろ Carbon 互換の File Manager プログラミングインタフェースを使用することを強く推奨しています。


参考文献


ページの先頭に戻る


更新日: 1999 年 10 月 5 日