ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
64 ビットに対応したデバイスドライバに対する入出力制御のサポート
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
例 15-15 の方法は、多くのドライバで正常に機能します。この代わりに、<sys/model.h> で提供されているデータ構造体マクロを使用して、アプリケーションとカーネルの間でデータを移動する方法があります。これらのマクロによってコードが整理され、機能の点から見てまったく同様に動作するようになります。
例 15-16 データ構造体マクロを使用したデータの移動
int xxioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p) { STRUCT_DECL(opdata, op); if (cmd != OPONE) return (ENOTTY); STRUCT_INIT(op, mode); if (copyin((void *)arg, STRUCT_BUF(op), STRUCT_SIZE(op))) return (EFAULT); if (STRUCT_FGET(op, flag) != XXACTIVE || STRUCT_FGET(op, size) > XXSIZE) return (EINVAL); xxdowork(device_state, STRUCT_FGET(op, size)); return (0); }
64 ビットのデバイスドライバでは、構造体マクロを使用すると、両方のサイズのデータ構造体でカーネルメモリーの同じ部分を使用できます。メモリーバッファーには、データ構造体のネイティブ形式 (つまり、LP64 形式と ILP32 形式) の内容が保持されます。構造体への各アクセスは、条件式によって実装されます。32 ビットのドライバとしてコンパイルされた場合は、1 つのデータモデル (ネイティブ形式) のみがサポートされます。条件式は使用されません。
64 ビットバージョンのマクロは、データ構造体のシャドウバージョンの定義に依存します。シャドウバージョンには、固定幅の型を含む 32 ビットインタフェースが記述されます。シャドウデータ構造体の名前は、ネイティブなデータ構造体の名前に「32」を追加することによって作成されます。将来の保守コストを軽減するために、便宜上、シャドウ構造体の定義はネイティブな構造体と同じファイル内に置きます。
これらのマクロは、次の引数を取ることができます。
struct キーワードのあとに入力されたデータ構造体のネイティブ形式の構造体名。
ioctl(9E) のモードパラメータから抽出されたユーザーのデータモデル (FILP32 や FLP64 など) を含むフラグワード。
これらのマクロで操作される構造体の特定のインスタンスを参照するために使用される名前。
構造体内のフィールドの名前。
マクロを使用すると、あるデータ項目のフィールドのみへのインプレース参照を行うことができます。マクロでは、データモデルに基づいた別のコードパスを取るための方法は提供されません。データ構造体内のフィールドの数が多い場合は、マクロを避けるべきです。また、これらのフィールドを参照する頻度が高い場合も、マクロを避けるべきです。
マクロでは、データモデル間の違いの多くがマクロの実装内に覆い隠されます。その結果、このインタフェースを使用して記述されたコードは一般に読みやすくなります。32 ビットのドライバとしてコンパイルされた場合、結果のコードは煩わしい #ifdefs が必要ないため簡潔になりますが、データ型のチェックは引き続き保持されます。
STRUCT_DECL(9F) と STRUCT_INIT(9F) を使用すると、スタック上の ioctl をデコードするためのハンドルと領域を宣言して初期化できます。STRUCT_HANDLE(9F) と STRUCT_SET_HANDLE(9F) は、スタック上の領域を割り当てることなくハンドルを宣言して初期化します。構造体が非常に大きいか、またはほかのデータ構造体に含まれている場合は、後者のマクロが役立つことがあります。
注 - STRUCT_DECL(9F) マクロと STRUCT_HANDLE(9F) マクロはデータ構造体の宣言まで拡張されるため、これらのマクロは C コードでこのような宣言を使用してグループ化されます。
構造体を宣言して初期化するためのマクロは次のとおりです。
structname データ構造体のための、handle という名前の構造体ハンドルを宣言します。STRUCT_DECL は、スタック上のネイティブ形式のための領域を割り当てます。ネイティブ形式は、構造体の ILP32 形式より大きいか、または等しいと見なされます。
handle のデータモデルを umodel に初期化します。このマクロは、STRUCT_DECL(9F) を使用して宣言された構造体ハンドルへの何らかのアクセスが行われる前に呼び出す必要があります。
handle という名前の構造体ハンドルを宣言します。STRUCT_DECL(9F) と対比されます。
handle のデータモデルを umodel に初期化し、addr を以降の操作に使用されるバッファーとして設定します。このマクロは、STRUCT_DECL(9F) を使用して宣言された構造体ハンドルへのアクセスの前に呼び出します。
構造体に対する操作を実行するためのマクロは次のとおりです。
handle によって参照される構造体のサイズを、その組み込みのデータモデルに応じて返します。
handle によって参照されるデータ構造体内の示されているフィールドを返します。このフィールドはポインタ以外の型です。
handle によって参照されるデータ構造体内の示されているフィールドを返します。このフィールドはポインタ型です。
handle によって参照されるデータ構造体内の示されているフィールドを値 val に設定します。val の型は、fieldname の型に一致します。このフィールドはポインタ以外の型です。
handle によって参照されるデータ構造体内の示されているフィールドを値 val に設定します。このフィールドはポインタ型です。
handle によって参照されるデータ構造体内の示されているフィールドのアドレスを返します。
handle で記述されたネイティブな構造体へのポインタを返します。
その他の構造体マクロのいくつかを次に示します。
指定されたデータモデルに基づいた struct_name のサイズを返します。
指定されたデータモデルに基づいたポインタのサイズを返します。