Solaris 7 のソフトウェア開発 (追補)

クラスタ対応デバイスドライバ用 DDI インタフェース

この機能は、Solaris 7 - 3/99 ソフトウェアリリースで追加されたものです。

Solaris オペレーティング環境がサポートするデバイスノードの種類は 2 つのクラスに分類できます。物理デバイスと疑似デバイスです。このクラス分類は、Sun Cluster によってデバイスノードが作成および使用されるときに重要になります。

デバイスドライバ開発者が Sun Cluster の将来のバージョンでも使用できる新しいインタフェースを採用できるように、デバイスクラスの概念を取り入れ、必要なインタフェースの変更と追加を行っています。Sun Cluster ソフトウェアがインストールされていないベースカーネルはこのようなデバイスクラスを無視するため、デバイスクラスが Solaris の動作に影響を与えることはありません。

デバイスドライバの詳細については、『Writing Device Drivers』を参照してください。

デバイスのクラス分類

Sun Cluster では 4 つの新しいデバイスクラスを採用します。このような新しいクラス分類は、Sun Cluster 環境におけるデバイスの拡張された動作に基づいています。

列挙型デバイス

ENUMERATED_DEV

ノード固有デバイス

NODESPECIFIC_DEV

大域デバイス

GLOBAL_DEV

ノード結合デバイス

NODEBOUND_DEV

ddi_create_minor_node(9F) ルーチンは、デバイスドライバによって作成されたマイナーノードによる分類であるこれらのデバイスクラスを引数として持ち、この引数として渡されたデバイスクラスをカーネルに伝えるように拡張されました。デバイスクラスについては、次の節を参照してください。

列挙型デバイス

列挙型デバイスとは、特定のデバイスノードとデバイスノードが存在するホストとの間で 1 対 1 の対応を持つ物理デバイスのことです。このクラスの例として、さまざまなディスクデバイスやテープデバイスがあります (たとえば、/dev/dsk/c0t0d0s0/dev/rmt/0l など)。ほとんどすべての物理デバイスがこのクラスに属します。このクラスは、すべての非疑似デバイスのデフォルトです。

ノード固有デバイス

ノード固有デバイスは、デバイスノードが開かれているホストについての固有な情報を持っているデバイスです。このようなデバイスの例として、/dev/kmem デバイスがあります。このデバイスを開くと、ローカルホスト上のホスト固有情報にアクセスできるようになります。特定のデバイスドライバについての情報を構成または収集するときに使用される管理疑似デバイスノードも、このクラスに入ります。Sun Cluster ソフトウェアを使用すると、クラスタ内のカーネルデバイスノードのインスタンスごとに、2 つのユーザーデバイスノードが必ず作成されます。したがって、目的のデバイスノードはローカルでも、リモートからでもアクセスできます。

大域デバイス

大域デバイスとは、ノード不変疑似デバイスのことです (たとえば、/dev/ip など)。原則として、デバイスのオープンインスタンス (iptcp など) は、クラスタ内のどのホストで開く動作が行われたかどうかに依存しません。デバイスごとに 1 つのコピーがカーネルに存在します。このデバイスクラスに対するすべてのデバイス入出力要求はローカルで実行され、このデバイスノードにはクラスタ内のリモートホストもアクセスできます。この動作は、システム内のすべての疑似デバイスのデフォルトです。

ノード結合デバイス

ノード結合デバイスとは、クラスタ全体の状態を管理する疑似デバイスのことです。原則的に、このデバイスは 1 つのノード上だけで開かなければなりません。/dev/ticotsord のようなデバイスがこのクラスに属します。自動フェイルオーバー機能を持つ、可用性の高い (HA) デバイスもこのクラスに属します。一度に存在する疑似ノードは 1 つだけですが、すべての開いたデバイスは同じノードに向けられます。ただし、HA デバイスは例外です。HA デバイスでは、ホストノードがデバイスユーザーにとっては透過的に変わる可能性があります。

マイナー番号領域の管理

dev_t は、メジャー番号領域とマイナー番号領域からなります。メジャー番号領域は Solaris により、マイナー番号領域はデバイスドライバ領域により管理されます。Sun Cluster では、マイナー番号の動作はユーザー領域とカーネル領域とで異なります。

クラスタ全体で有効な dev_t

歴史的な理由のため、デバイスノード (とそのパス) は整数型 dev_t で識別されます。dev_t は、プログラマやシステム管理者が通常使用するシステムインタフェースの一部です。stat(2) システムコールとバックアップユーティリティは dev_t を直接処理します。dev_t は、また、デバイスドライバ開発者向けのプログラミングインタフェースでもあります。

Sun Cluster は、プロセスが実行されたホストにかかわらず、2 つの等しい dev_t は同じデバイスを指すと仮定します。このモデルは、(この特徴に基づいて書かれた) プログラムが、2 つのデバイスの等価性を確立する時に有効です。Sun Cluster は、マイナー番号の二重ビューを導入し、二重ビューを実装するために必要なインタフェースを導入します。カーネルの中で、dev_t はドライバのメジャー番号に対応し、さらに、そのドライバが ddi_create_minor_node(9F) で作成したマイナー番号に対応しています。Sun Cluster では、ユーザー領域から使用される時のマイナー番号である外部マイナー番号がデバイス構成マネージャによって管理され、一意なクラスタ全体で使用できる番号を割り当てています。

この二重番号付け方式は、残念ながら 1 つの欠点を持っています。つまり、カーネルで作成された特定のマイナー番号が、ユーザー領域では異なるマイナー番号で使用されている可能性があります。この矛盾は、マイナー番号のパターンからいくつかのデバイスの特性を確認できると期待しているユーザー領域プログラムには役立ちません。

この矛盾の例として、マイナー番号のビットパターンを使用して、ディスクの特定のスライスやテープデバイスの密度などを指定する場合などがあります。このクラスの問題は、主に、大域的に一意なインスタンス番号を使用することによって軽減できます。デバイスのインスタンス番号をマイナー番号に符号化することによって、ドライバはクラスタ全体で一意な dev_t の値が作成されます。つまり、カーネル領域とユーザー領域間で値が異なるマイナー番号が発生する問題を回避できます。

標準の Solaris エントリポイント (opencloseioctl など) で渡されるすべての dev_t 値はカーネルのマイナー番号を符号化します。getminor(9F) インタフェースを使用すると、このマイナー番号を抽出できます。しかし、dev_t 値が ioctl データの一部としてユーザー領域から渡された場合、その dev_t 値はユーザー領域で符号化されたマイナー番号を持っています。ドライバが内部マイナー番号と外部マイナー番号の間で正しく対応付けができるように、新しい DDI インタフェース ddi_getiminor(9F) が導入されました。

デバイスインタフェース

次のインタフェースはドライバを設定して、使用できる状態にします。


int ddi_create_minor_node(dev_info_t *dip, char *name, 
int spec_type, int minor_num, char *node_type, int flag);

ddi_create_minor_node(9F) は、/devices ディレクトリに作られ、dip で指定したデバイスを参照する、デバイスマイナーノードを作成します。デバイスがクローンデバイスの場合、flagCLONE_DEV に設定されます。クローンデバイスでない場合、flag は 0 に設定されます。クラスタ化した環境で使用されることを目的とするデバイスドライバの場合、flag はデバイスノードクラス GLOBAL_DEVNODEBOUND_DEVNODESPECIFIC_DEV、または ENUMERATE_DEV を指定しなければなりません。

ユーザーが使用するデバイス番号とカーネルデバイス番号との間での変換を行うために、以下の新しいインタフェースが使用されます。


minor_t ddi_getiminor(dev_t dev);

ddi_getiminor(9F) はデバイス番号としてマイナー番号を抽出します。