Solaris 2.x への移行

デバイスドライバと STREAMS デバイスドライバ

Solaris 2.6 では、デバイスドライバに多くの変更点があります。たとえば、新しい DDI/DKI ルーチン、Solaris SPARC DDI 固有ルーチン、新しいソフトウェアの特性、ロード可能なドライバなどです。また、以前からあったデバイスに関する多くの問題 (割込み、DVMA、メモリマッピングなど) を、ドライバが意識しなくて済むようになりました。

デバイスドライバのインタフェース

以前の SunOS リリースでは、ドライバの作成者はデバイスドライバインタフェースの変更を処理しなければなりませんでした。通常、オペレーティングシステムのリリースごとに移植を行なっていました。さらに、プラットホームごとにインタフェースが異なるため、各プラットホームに合ったデバイスドライバが必要でした。サードパーティのデバイスドライバのリリースには、デバイスドライバを統合するためにオペレーティングシステムの再設定および再構築を行う複雑なスクリプトも中には含まれていました。したがって、デバイスドライバのサポートと保守にはコストがかかりました。

SunOS システムの以前のリリース (SunOS 4.1.3 ソフトウェア以前) と違って、Solaris 2.6 環境のデバイスドライバインタフェースは統一化されて、Solaris 2.6 SPARC DDI/DKI と呼びます。Solaris 2.6 SPARC DDI/DKI は、サポートされているすべてのプラットホームと、これらのプラットホームの Solaris 環境のすべての将来のリリースにデバイスドライバのバイナリ互換性を提供するために作成されました。

DDI/DKI という用語は、SVR4 リリースにある元の仕様から取ったものです。これは、デバイスドライバインタフェース / デバイスカーネルインタフェースを表します。インタフェースは次の 3 グループに分割されます。

DDI/DKI

DDI/DKI インタフェースは SVR4 で標準化されており、動作しているプラットホームとは関係なく SVR4 のすべての処理系で共通です。

DKI

DKI 専用インタフェースは DDI/DKI インタフェースと同様に共通であり、すべての SVR4 処理系でサポートされます。ただし、Sytem V の将来のリリースでサポートされる保証はありません。

DDI

DDI 専用インタフェースは、アーキテクチャ固有のものです。たとえば、デバイスとシステム固有ハードウェアへのアクセスおよび制御方法 (つまり、I/O レジスタ、DMA サービス、割り込み、およびメモリマッピング) が固有です。これらのインタフェースは、その他の SVR4 処理系での機能は保証されていません。

こういった特長によりドライバのサポートと保守のコストを効率よく下げることができます。この多数の SPARC プラットホームと結合した機能は、多くの新しいサードパーティのハードウェア開発者の役に立つでしょう。

このレベルのバイナリ互換性を提供することにより、いまではサードパーティのハードウェア開発者は彼らのドライバハードウェアと一緒に DDI 準拠のデバイスドライバをシュリンクラップ形式にパッケージ化することができます。新しいドライバパッケージのインストールは、いまでは完全に自動化されています。自動構成を行うカーネルにより、ドライバを追加または削除するためにカーネルを再コンパイルする必要はなくなりました。したがって、Solaris 2.6 環境の DDI 準拠デバイスドライバは、他のすべての市販のソフトウェア製品と同様に扱うことができます。

Solaris 2.6 DDI/DKI では、DDI 専用インタフェースは Solaris 2.6 DDI/DKI をサポートするすべてのシステムに共通です。Sun Common SCSI Atchitecture (SCSA) のインタフェース、およびマルチスレッドカーネルでドライバを正常に機能させるために使用するロックインタフェースもまた、Solaris 2.6 環境では DDI 専用インタフェースとみなすことができるので注意してください。

SCSA により、デバイスドライバはホストアダプタのインプリメンテーションに関するプラットホーム固有の細部を考慮しなくてもよくなりました。SCSA を使用すると、SCSI ドライバはサポートされるすべてのプラットホームで実行できます。

上記のカテゴリのインタフェースだけを使うように制限したデバイスドライバを、「Solaris 2.6 DDI/DKI 準拠」といいます。 Solaris 2.6 DDI/DKI に準拠したデバイスドライバを一般に「DDI に準拠したデバイスドライバ」といいます。

マニュアルページ

ドライバルーチン、構造体、および DDI/DKI を構成するサポートルーチンに関するマニュアルページは、『SunOS Reference Manual』セクション 9「DDI and DKI」にある以下のセクションにあります。詳細については Intro(9) のマニュアルページを参照してください。

devinfo コマンド

Solaris 2.6 の devinfo コマンドは SunOS 4.x の devinfo とは機能が異なります。新しい prtconf(1M) コマンドは SunOS 4.x の devinfo コマンドで表示した情報を表示します。次の例で各コマンドの出力を示します。

4.1system% devinfo
Node 'SUNW,Sun 4/50', unit #0 (no driver)
        Node 'packages', unit #0 (no driver)
        Node 'openprom', unit #0 (no driver)
        Node 'zs', unit #0
        Node 'zs', unit #1
        Node 'audio', unit #0
        Node 'eeprom', unit #0 (no driver)
        Node 'counter-timer', unit #0 (no driver)
        Node 'memory-error', unit #0 (no driver)
        Node 'interrupt-enable', unit #0 (no driver)
        Node 'auxiliary-io', unit #0 (no driver)
        Node 'sbus', unit #0
                Node 'dma', unit #0
                Node 'esp', unit #0
                        Node 'sr', unit #0
                        Node 'sd', unit #0
                Node 'le', unit #0
                Node 'cgsix', unit #0
        Node 'memory', unit #0 (no driver)
        Node 'virtual-memory', unit #0 (no driver)
        Node 'fd', unit #0
        Node 'options', unit #0 (no driver)

5.3system% prtconf
System Configuration:  Sun Microsystems  sun4c
Memory size: 32 Megabytes
System Peripherals (Software Nodes):

SUNW,Sun 4_75
    packages (driver not attached)
        disk-label (driver not attached)
        deblocker (driver not attached)
        obp-tftp (driver not attached)
    openprom (driver not attached)
    zs, instance #0
    zs, instance #1
    audio (driver not attached)
    eeprom (driver not attached)
    counter-timer (driver not attached)
    memory-error (driver not attached)
    interrupt-enable (driver not attached)
    auxiliary-io (driver not attached)
    sbus, instance #0
        dma, instance #0
        esp, instance #0
            sd (driver not attached)
            st (driver not attached)
            sd, instance #0
            sd, instance #1 (driver not attached)
            sd, instance #2 (driver not attached)
            sd, instance #3
            sd, instance #4 (driver not attached)
            sd, instance #5 (driver not attached)
            sd, instance #6
        le, instance #0
        cgsix, instance #0
    memory (driver not attached)
    virtual-memory (driver not attached)
    fd (driver not attached)
    options, instance #0
    pseudo, instance #0

移行に関する留意点

自動構成を行うカーネルを使用すると、Solaris 2.6 ドライバは他のタイプのドライバよりも SBus ドライバに似ています。すべてのドライバがロード可能で、カーネルの構成は必要ありません。

SunOS 4.x ソフトウェアでは、1 度に 1 つのプロセッサしかカーネルに存在できません。これはカーネル全体で 1 つのマスタロックを使うことで実現されていました。プロセッサがカーネルコードを実行したいときは、ロックを獲得し (他のプロセッサがロックで保護されたコードを実行するのを防ぐ)、終了したらロックを解放します。

Solaris 2.6 カーネルはマルチスレッドです。1 つのマスタロックの代わりに、コードの細分化された領域を保護するための多数の細分化されたロックがあります。たとえば、特定の v ノードへのアクセスを保護するカーネルロックや、i ノードを保護するカーネルロックがあります。一回に 1 つのプロセッサしか v ノードを処理するコードを実行できませんが、別のプロセッサが i ノードにアクセスすることは可能です。これにより多くの並列化が可能になります。

マルチスレッドカーネルは、ドライバの設計に大きな影響を与えます。splN/splr ペアを使用した古いモデルは (ユニプロセッサまたはマルチプロセッサマシンにおいて [厳密には、splN/splr ペアは動作します。ただし、それはマルチプロセッサシステム上では非効率的です。つまり、splN/splr は割り込みをブロックしますが、マルチプロセッサ環境においてデータ構造を保護するという意味では効果はありません。] ) もはや動作しません。そのかわりに MT スタイルのロックを選択することができます。ドライバの最も一般的なロックは、相互排他ロック、mutexes (仕様では splN/splr ペアとほぼ同等)、および条件変数 (sleep()/wakeup() 同期化とほぼ同等) です。

sleep() を明示的に呼び出すまではプロセッサを所有しているという古い概念は、もはや成立しません。カーネルがプリエンプティブになっているため、CPU はスレッドからスレッドへと切り換えられます。したがって、デバイスレジスタや共有データ構造などへの同時アクセスを防ぐため、適切な MT ロックプリミティブを使用しなければなりません。

単純なデバイスドライバ用のドライバコードは、主にカーネルインタフェースルーチンで構成されていますが、そのかなりの部分が変更されます。ただし、分かりやすい変更です。SCSI ドライバのように大量のデバイス固有の処理コードを持つ複雑なデバイスドライバの場合は、ドライバインタフェースの変更はわずかです。このドライバインタフェースは、カーネルからドライバへのインタフェースか、ドライバからカーネルへのインタフェースか、または、ドライバからドライバへのインタフェースです。

Solaris 2.6 環境でどのようにドライバをサポートするかを決定する前に、ドライバがどのように動作するかについてもう一度調べるようにしてください。SunOS 4.x のドライバの動作を調べてください (特定の処理系での動作ではなく一般的な動作)。エクスポートしていたインタフェース、提供していた ioctl()、ハードウェアの動作、ドライバがサポートしていたハードウェアの特徴、また、ドライバが複数の open() 呼び出しをサポートしていたかどうかなどです。

これらの変更はドライバに影響を与えるため、次の点を検討してください。

STREAMS

STREAMS モジュールでの変更点は、透過的な I/O 制御、ストリームへのモジュールの自動プッシュ、新しいメッセージタイプなどです。

透過的な ioctl()

SunOS 4.x リリースでは、特定のドライバは ioctl() 要求を行う前は STREAMS ドライバであったということを知っておく必要があります。

STREAMS 以外のドライバについては、次のように直接 ioctl() 要求ができます。

ioctl(fd, DRIVER_IOCTL, arg);

STREAMS ドライバについては、次のように strioctl 構造を設定した後で使用しなければなりません。

ioctl(fd, I_STR, &strioctl);

ドライバが STREAMS ベースであったかどうかを判定する簡単な方法はありませんでした。現在では、ストリームヘッドに対する認識されない ioctl() はドライバに渡されるので、ドライバが STREAMS ベースであったかどうかを知る必要がなくなりました。

特に透過的 ioctl() をサポートするため、新しいメッセージタイプが Solaris 2.6 リリースに追加されました。現在、カーネルとの間のユーザデータの転送をストリームヘッドに通知するための「コピーイン」 および「コピーアウト」 メッセージがあります。

STREAMS ドライバを書く詳細については、『STREAMS Programming Guide』を参照してください。

autopush コマンド

SunOS 4.x の streamtab 構造体では、デバイスが open() のときに特定の STREAMS モジュールをプッシュするようドライバ側で指定できました。

Solaris 2.6 では、システム管理者と autopush(1M) コマンドが、いつ STREAMS モジュールをプッシュするかを指定します。必要な場合、ドライバのインストール時に autopush を実行できます。

STREAMS モジュールのプッシュに関する詳しい情報については、『STREAMS Programming Guide』を参照してください。

Solaris 2.x ドライバアーキテクチャ

現在サポートされるハードウェアプラットフォームのすべてにバイナリ互換性を達成するため、DDI インタフェースはアーキテクチャ概念に沿って慎重に設計されました。基礎となる概念、つまり device ツリーは、元の SPARCstationTM 設計における devinfo ツリーの拡張です。デバイスツリーの各ノードはデバイス情報構造体または「dev_info ノード」 によって記述されます。ツリーの最下部のノードをリーフノードといいます。ディスク、テープドライブ、フレームバッファ、I/O カード、およびネットワークインタフェースなどのほとんどのデバイスは、リーフノードに関連付けられるリーフデバイスの例です。対応するデバイスドライバをリーフドライバといいます。

ツリーにおける中間ノードは一般にバスと関連づけられます (たとえば SBus、SCSI、VME)。これらのノードを「nexus ノード」といい、それらに関連づけられるドライバを「nexus ドライバ」といいます。バス nexi は特定の要素と関連づけられるアーキテクチャの詳細をカプセル化するためのエンティティです。

現在、Solaris 2.6 DDI/DKI だけがリーフドライバnexusドライバの 1 つの型、SCSI ホストバス・アダプタドライバの記述をサポートしています。

デバイスツリー構造はノード間に正式な親子関係を確立します。この親子関係はプラットフォームアーキテクチャの独立性にとって重要なポイントです。

リーフドライバがプラットホーム依存 (たとえば DMA マッピング) のサービスを必要とする場合は、システムはサービスを提供するために要求をその親の呼び出しへと透過的にに変換します。サービスを提供するのは常に nexus ドライバです。それぞれの nexus ドライバはサービスを提供するために、今度は要求をその親に渡すことができます。このアプローチにより、リーフドライバはプラットフォームのアーキテクチャとは関係なく機能することができます。