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

第 2 章 ソフトウェア開発

この章では、以下のソフトウェア開発情報について説明します。


注 -

最新のマニュアルページを参照するには、man コマンドを使用してください。Solaris 7 - 11/99 のマニュアルページには、「Solaris 7 Reference Manual Collection」には記載されていない新機能の情報が提供されています。


SPARC: SCSI HBA ドライバ用 DR サポート

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

このリリースでは、動的再構成 (DR) のサポートが SCSI デバイス用に更新されました。SCSI HBA ドライバは、(以前『Writing Device Drivers』の「Converting Device Drivers to Support Hotplugging」で記述されていた) cb_ops 構造体なしで、動的再構成をサポートできるようになりました。

新しいデフォルトの SCSI HBA ドライバエントリポイント

ホットプラグ操作の最小セットをサポートするには、ドライバにバスの休止、バスの休止解除、およびリセットのサポートが実装されている必要があります。scsi_hba_tran(9S) 構造体は、これらの新しい操作をサポートするために拡張されました。ハードウェアがバスの休止、バスの休止解除、およびリセットを必要としない場合は、ドライバを変更する必要はありません。

次の新しいフィールドが scsi_hba_tran 構造体に追加されました。


int (*tran_quiesce)(dev_info_t *hba_dip);
int (*tran_unquiesce)(dev_info_t *hba_dip);
int (*tran_bus_reset)(dev_info_t *hba_dip, int level);

新しいドライバエントリポイントについては、次の節で説明します。

tran_quiesce()tran_unquiesce()

SCSI バスに対して、休止と休止解除のサポートを実装するように設定します。


#include <sys/scsi/scsi.h>

int prefix tran_quiesce(dev_info_t *hba_dip);

int prefix tran_unquiesce(dev_info_t *hba_dip);

ホットプラグをサポートするよう設定されていないバス上にある SCSI デバイスについて動的再構成 (DR) をサポートするには、HBA ドライバにより tran_quiesce(9E)tran_unquiesce(9E) を実装する必要があります。

scsi_hba_tran(9S) 構造体にある tran_quiesce()tran_unquiesce() ベクトルは、HBA ドライバに attach(9E) を実行して HBA エントリポイントを指すようにする際に初期化する必要があります。こうしておくと、ユーザーが休止および休止解除の操作を始めるときに呼び出されます。

tran_quiesce(9E) は SCSA フレームワークにより呼び出され、SCSI バスに接続されたデバイスの再構成が始まる前と再構成の間、SCSI バス上のすべての動作を休止させます。tran_unquiesce(9E) は、再構成操作が終了してから SCSA フレームワークによって呼び出され、SCSI バス上の動作を再開します。

HBA ドライバは、中断されていたコマンドがすべて終了して正常終了を示すメッセージが返されるまで、tran_quiesce(9E) を操作している必要があります。HBA はバスを休止させた後、SCSA フレームワークが対応する tran_unquiesce(9E) エントリポイントを呼び出すまで、ターゲットドライバからの新しい入出力要求を待ち行列に入れておかなければなりません。

HBA ドライバは、バスが静止している間に HBA が待ち行列に入れたターゲットドライバの入出力要求を起動することによって、tran_unquiesce(9E) の呼び出しを行います。

tran_bus_reset()

tran_bus_reset(9E) は、ターゲットをリセットすることなく SCSI バスをリセットする必要があります。


#include <sys/scsi/scsi.h>

	int prefix tran_bus_reset(dev_info_t *hba_dip, int level);

level には次を指定します。

RESET_BUS

ターゲットではなく、SCSI バスのみをリセットする

scsi_hba_tran(9S) 構造体の tran_bus_reset() ベクトルは、ユーザーがバスリセットを開始したときに呼び出される HBA エントリポイントを指すように HBA ドライバが attach(9E) を実行する間に、初期化される必要があります。

実装はハードウェアにより異なります。ターゲットに影響を与えることなく SCSI バスをリセットするのが不可能な場合は、HBA ドライバは RESET_BUS の実行に失敗するか、このベクトルを初期化しません。

詳細は、『Writing Device Drivers』の「Converting Device Drivers to Support Hotplugging」を参照してください。

PCI ホットプラグドライバの問題点

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

Intel プラットフォーム用の PCI デバイスドライバの一部は、レジスタの値が POWER ON サイクルの後も有効であるという前提で作成されています。しかし、BIOS がハードウェアを正しく初期化したことを前提とすることはできません。

ホットプラグ機能の詳細は、『Writing Device Drivers』の「Converting Device Drivers to Support Hotplugging」を参照してください。

8 ビットビジュアルサポート

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

8 ビットビジュアル共有ライブラリにより、24 ビットのビジュアル精度しかサポートされていないハードウェアで 8 ビットビジュアルアプリケーションの実行が可能になり、一連の変換機能が提供されます。この機能は、8 ビットビジュアルサポートを要求するアプリケーションに対して、デバイスドライバ内蔵の 24 ビット描画機能の呼び出しを使用します。これは、24 ビットビジュアルサポートのハードウェアプラットフォーム上にイメージを描画する前に、8 ビット疑似カラーのカラーマップピクセルデータを 24 ビットトゥルーカラーのカラーマップピクセルデータに変換することによって実行されます。

Solaris 7 64 ビット 開発ガイド』の更新

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

Solaris 7 64 ビット 開発ガイド』で更新された内容は、次のとおりです。

クラスタ対応デバイスドライバ用 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) はデバイス番号としてマイナー番号を抽出します。