ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
デバイスドライバは、動的にロード可能である必要があります。ドライバは、メモリー資源の節約に役立つように、アンロード可能にもなっています。また、アンロード可能なドライバは、テスト、デバッグ、パッチ適用がより容易でもあります。
ドライバのロードとアンロードをサポートするには、各デバイスドライバが _init(9E)、_fini(9E)、および _info(9E) エントリポイントを実装する必要があります。次の例は、ロード可能なドライバインタフェースの標準的な実装を示しています。
例 6-1 ロード可能なインタフェースのセクション
static void *statep; /* for soft state routines */ static struct cb_ops xx_cb_ops; /* forward reference */ static struct dev_ops xx_ops = { DEVO_REV, 0, xxgetinfo, nulldev, xxprobe, xxattach, xxdetach, xxreset, nodev, &xx_cb_ops, NULL, xxpower, ddi_quiesce_not_needed, }; static struct modldrv modldrv = { &mod_driverops, "xx driver v1.0", &xx_ops }; static struct modlinkage modlinkage = { MODREV_1, &modldrv, NULL }; int _init(void) { int error; ddi_soft_state_init(&statep, sizeof (struct xxstate), estimated_number_of_instances); /* further per-module initialization if necessary */ error = mod_install(&modlinkage); if (error != 0) { /* undo any per-module initialization done earlier */ ddi_soft_state_fini(&statep); } return (error); } int _fini(void) { int error; error = mod_remove(&modlinkage); if (error == 0) { /* release per-module resources if any were allocated */ ddi_soft_state_fini(&statep); } return (error); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); }
次の例は、標準的な _init(9E) インタフェースを示しています。
例 6-2 _init() 関数
static void *xxstatep; int _init(void) { int error; const int max_instance = 20; /* estimated max device instances */ ddi_soft_state_init(&xxstatep, sizeof (struct xxstate), max_instance); error = mod_install(&xxmodlinkage); if (error != 0) { /* * Cleanup after a failure */ ddi_soft_state_fini(&xxstatep); } return (error); }
ドライバは、1 回限りの資源割り当てまたはデータ初期化を _init() でのドライバのロード中に実行します。たとえば、ドライバは、そのドライバに対してグローバルな mutex をすべてこのルーチン内で初期化します。ただし、ドライバは _init(9E) を使用して、デバイスの特定のインスタンスと関係があるものを割り当てたり、初期化したりしません。インスタンスごとの初期化は、attach(9E) で実行する必要があります。たとえば、プリンタのドライバが一度に複数のプリンタを処理できる場合、そのドライバは、各プリンタインスタンスに固有の資源を attach() で割り当てます。
注 - _init(9E) が mod_install(9F) を呼び出したあとは、システムがそのデータ構造体をコピーまたは変更する可能性があるため、ドライバは modlinkage(9S) 構造体に接続されたデータ構造体を変更しません。
次の例は、_fini() ルーチンを示しています。
int _fini(void) { int error; error = mod_remove(&modlinkage); if (error != 0) { return (error); } /* * Cleanup resources allocated in _init() */ ddi_soft_state_fini(&xxstatep); return (0); }
同様に、ドライバは _fini() で、_init() で割り当てられた資源をすべて解放します。ドライバは、システムモジュールリストから自身を削除する必要があります。
注 - ドライバがハードウェアインスタンスに接続されているときに _fini() が呼び出される可能性があります。この場合は、mod_remove(9F) が失敗を返します。そのため、mod_remove() が成功を返すまで、ドライバ資源を解放しません。
次の例は、_info(9E) ルーチンを示しています。
int _info(struct modinfo *modinfop) { return (mod_info(&xxmodlinkage, modinfop)); }