Go to main content
Oracle® Solaris 11.3 デバイスドライバの記述

印刷ビューの終了

更新: 2016 年 11 月
 
 

デバイスアクセス (文字ドライバ)

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() の主な機能は、オープンの要求が許可されていることの確認です。open(9E) の構文は次のとおりです。

int xxopen(dev_t *devp, int flag, int otyp, cred_t *credp);

ここでは:

devp

デバイス番号へのポインタ。ドライバがマイナー番号を変更できるように、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 のメジャー番号を変更してはいけません。ドライバは、使用可能なマイナー番号を内部的に常時追跡する必要があります。

flag

デバイスが読み取り (FREAD)、書き込み (FWRITE)、またはその両方のために開かれているかどうかを示すビットを含むフラグ。open(2) システムコールを発行するユーザースレッドは、デバイスへの排他的アクセスを要求するか (FEXCL)、またはオープンがどのような理由でもブロックされないように指定する (FNDELAY) こともできますが、ドライバはその両方のケースを実現する必要があります。プリンタなどの書き込み専用デバイスのドライバによって、読み取りのための open(9E) が無効と見なされることがあります。

otyp

open() が呼び出された方法を示す整数。ドライバは、otyp の値がデバイスに適していることを確認する必要があります。文字ドライバの場合、otypOTYP_CHR です (open(9E) のマニュアルページを参照)。

credp

ユーザー ID やグループ ID などの、呼び出し元に関する情報を含む資格構造体へのポインタ。ドライバは、この構造体を直接検査するのではなく、代わりに drv_priv(9F) を使用して root 権限の一般的なケースを確認する必要があります。この例では、root または PRIV_SYS_DEVICES 特権を持つユーザーのみが、書き込みのためのデバイスのオープンを許可されています。

次の例は、文字ドライバの open(9E) ルーチンを示しています。

使用例 70  文字ドライバの 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() エントリポイント (文字ドライバ)

close(9E) の構文は次のとおりです。

int xxclose(dev_t dev, int flag, int otyp, cred_t *credp);

close() は、マイナーデバイスの使用を完了するために必要なクリーンアップをすべて実行し、デバイス (およびドライバ) を次回のオープンのために準備します。たとえば、open ルーチンが、排他的アクセス (FEXCL) フラグを使用して呼び出されているとします。close(9E) を呼び出すと、追加の open ルーチンを続行できるようになります。close(9E) が実行する可能性のあるほかの機能は次のとおりです。

  • 戻る前の、出力バッファーからの入出力の排出の待機

  • テープの巻き戻し (テープデバイス)

  • 電話回線の切断 (モデムデバイス)

入出力の排出を待機するドライバは、フロー制御などの外部条件のために排出が滞ると、永久に待機する可能性があります。この問題を回避する方法については、スレッドがシグナルを受信できないを参照してください。