ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 10 8/11 Information Library (日本語) |
パート I Solaris プラットフォーム用デバイスドライバの設計
64 ビットに対応したデバイスドライバに対する入出力制御のサポート
21. ドライバのコンパイル、ロード、パッケージ化、およびテスト
1 つ以上のアプリケーションプログラムによるデバイスへのアクセスは、open(9E) エントリポイントと close(9E) エントリポイントを通して制御されます。文字デバイスを表す特殊ファイルへの open(2) システムコールを呼び出すと、常にドライバの open(9E) ルーチンが呼び出されます。特定のマイナーデバイスの場合は、open(9E) を複数回呼び出すことができます。close(9E) ルーチンは、そのデバイスへの最後の参照が削除された場合にのみ呼び出されます。デバイスがファイル記述子を通してアクセスされている場合、close(9E) の最後の呼び出しは、close(2) または exit(2) システムコールの結果として実行されることがあります。デバイスがメモリーマッピングを通してアクセスされている場合、close(9E) の最後の呼び出しは、munmap(2) システムコールの結果として実行されることがあります。
open() の主な機能は、オープンの要求が許可されていることの確認です。open(9E) の構文は次のとおりです。
int xxopen(dev_t *devp, int flag, int otyp, cred_t *credp);
各表記の意味は次のとおりです。
デバイス番号へのポインタ。ドライバがマイナー番号を変更できるように、open() ルーチンにはポインタが渡されます。ドライバは、このポインタを使用して、デバイスのマイナーインスタンスを動的に作成できます。1 つの例として、ドライバが開かれた場合は常に新しい仮想端末を作成する疑似端末ドライバがあります。マイナー番号を動的に選択するドライバは通常、attach(9E) で ddi_create_minor_node(9F) を指定してマイナーデバイスノードを 1 つだけ作成したあと、makedevice(9F) と getmajor(9F) を使用して *devp のマイナー番号コンポーネントを変更します。
*devp = makedevice(getmajor(*devp), new_minor);
新しいマイナー番号のために ddi_create_minor_node(9F) を呼び出す必要はありません。ドライバが *devp のメジャー番号を変更してはいけません。ドライバは、使用可能なマイナー番号を内部的に常時追跡する必要があります。
デバイスが読み取り (FREAD)、書き込み (FWRITE)、またはその両方のために開かれているかどうかを示すビットを含むフラグ。open(2) システムコールを発行するユーザースレッドは、デバイスへの排他的アクセスを要求するか (FEXCL)、またはオープンがどのような理由でもブロックされないように指定する (FNDELAY) こともできますが、ドライバはその両方のケースを適用します。プリンタなどの書き込み専用デバイスのドライバによって、読み取りのための open(9E) が無効と見なされることがあります。
open() が呼び出された方法を示す整数。ドライバは、otyp の値がデバイスに適していることを確認する必要があります。文字ドライバの場合、otyp は OTYP_CHR です (open(9E) のマニュアルページを参照)。
ユーザー ID やグループ ID などの、呼び出し元に関する情報を含む資格構造体へのポインタ。ドライバは、この構造体を直接検査するべきではなく、代わりに drv_priv(9F) を使用して root 権限の一般的なケースを確認します。この例では、root または PRIV_SYS_DEVICES 特権を持つユーザーのみが、書き込みのためのデバイスのオープンを許可されています。
次の例は、文字ドライバの open(9E) ルーチンを示しています。
例 15-2 文字ドライバの open(9E) ルーチン
static int xxopen(dev_t *devp, int flag, int otyp, cred_t *credp) { minor_t instance; if (getminor(*devp) /* if device pointer is invalid */ return (EINVAL); instance = getminor(*devp); /* one-to-one example mapping */ /* Is the instance attached? */ if (ddi_get_soft_state(statep, instance) == NULL) return (ENXIO); /* verify that otyp is appropriate */ if (otyp != OTYP_CHR) return (EINVAL); if ((flag & FWRITE) && drv_priv(credp) == EPERM) return (EPERM); return (0); }
close(9E) の構文は次のとおりです。
int xxclose(dev_t dev, int flag, int otyp, cred_t *credp);
close() は、マイナーデバイスの使用を完了するために必要なクリーンアップをすべて実行し、デバイス (およびドライバ) を次回のオープンのために準備します。たとえば、open ルーチンが、排他的アクセス (FEXCL) フラグを使用して呼び出されているとします。close(9E) を呼び出すと、追加の open ルーチンを続行できるようになります。close(9E) が実行する可能性のあるほかの機能は次のとおりです。
戻る前の、出力バッファーからの入出力の排出の待機
テープの巻き戻し (テープデバイス)
電話回線の切断 (モデムデバイス)
入出力の排出を待機するドライバは、フロー制御などの外部条件のために排出が滞ると、永久に待機する可能性があります。この問題を回避する方法については、「スレッドがシグナルを受信できない」を参照してください。