Solaris 動的トレースガイド

型の名前空間

ここでは、D の名前空間と型関連の問題について説明します。ANSI-C をはじめとする従来の言語では、型の可視性は、その型が関数やその他の宣言内に入れ子になっているかどうかによって決定されます。C プログラムの外側 (外部スコープ) で宣言された型には、単一の大域名前空間が関連付けられます。このため、これらの型は、プログラム内のどの位置でも可視的に使用できます。外部スコープの代表例として、C ヘッダーファイルに定義された型が挙げられます。D では、従来の言語とは異なり、複数の外部スコープの型にアクセスできます。

D 言語は、オペレーティングシステムカーネル、これに関連付けられているロード可能なカーネルモジュールのセット、システム上で実行されるユーザープロセスなど、ソフトウェアスタックの複数の層を動的に監視できるように設計されています。単一の D プログラムでプローブをインスタンス化し、複数のカーネルモジュールのデータや、独立したバイナリオブジェクトにコンパイルされるその他のソフトウェア構成要素のデータを収集できます。このため、DTrace や D コンパイラに、使用可能な型として、同じ名前の複数のデータ型 (通常、定義はそれぞれ異なる) が提供されることがあります。この問題に対処するため、D コンパイラでは、各型に、それを含むプログラムオブジェクト別の名前空間が割り当てられます。特定のプログラムオブジェクトの型にアクセスするには、型名に、オブジェクト名と逆引用符 (`) で表されるスコープ演算子を指定します。

たとえば、カーネルモジュール foo に次の C 型宣言が含まれているとします。

typedef struct bar {
	int x;
} bar_t;

この場合、D から struct bar 型や bar_t 型にアクセスするには、次のように型名を使用します。

struct foo`bar				foo`bar_t

逆引用符の演算子は、型名が適切であれば、どのような状況でも使用できます。たとえば、D 変数宣言の型を指定するときや、D プローブ節にキャスト式を指定するときに使用できます。

D コンパイラでは、それぞれ名前 CD を使用する、2 つの特殊な組み込み型の名前空間を使用できます。C の型の名前空間は、最初に、int のような標準 ANSI-C 組み込み型に割り当てられています。さらに、C プリプロセッサ cpp(1) によって実行された dtrace -C オプションの結果得られた型定義が処理され、C スコープに追加されます。その結果、コンパイルエラーを発生させずに、別の型の名前空間で使用可能な型宣言を含む C ヘッダーファイルを追加できます。

D の型の名前空間は、最初に、intstring をはじめとする D の組み込み型と、uint32_t などの D の組み込み型の別名に割り当てられています。D プログラムソース内の型宣言は、新しく宣言されるたびに、自動的に D の型の名前空間に追加されます。D プログラム内で、ほかの名前空間のメンバーの型から成る複合型 (struct など) を作成した場合、宣言により、そのメンバーの型が D の名前空間にコピーされます。

D コンパイラは、名前空間が明示的に指定されていない (逆引用符の演算子が使用されていない) 型宣言を検出すると、有効な型の名前空間を検索し、指定された型名と一致する型名を見つけようとします。常に C の名前空間が最初に検索され、そのあとで D の名前空間が検索されます。C と D のどちらの名前空間でも型名が見つからない場合、有効なカーネルモジュールの型の名前空間が、カーネルモジュール ID の昇順で検索されます。この順番では必ず、コアカーネルを構成するバイナリオブジェクトがロード可能なカーネルモジュールより先に検索されます。ただし、ロード可能なモジュール間の検索順序は指定されていません。ロード可能なカーネルモジュールに定義された型にアクセスするときは、ほかのカーネルモジュールとの型名の競合を避けるため、スコープ演算子を使用してください。

D コンパイラは、C のインクルードファイルにアクセスすることなくオペレーティングシステムのソースコードに関連付けられた型に自動的にアクセスするため、Solaris のコアカーネルモジュールから提供される圧縮形式の ANSI-C デバッグ情報を使用します。このシンボリックなデバッグ情報は、システム上のすべてのカーネルモジュールに提供されるわけではありません。ユーザーがアクセスしようとした型の名前空間のモジュールに、DTrace で使用される圧縮形式の C デバッグ情報が含まれていない場合、D コンパイラからエラーが返されます。