デバイスドライバ

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動先: 案内検索

テンプレート:OS デバイスドライバは、グラフィックディスプレイプリンタイーサネットボードなど、ある特定の入出力デバイス(拡張カード周辺機器などのハードウェア)を制御し、アプリケーションソフトウェアに対して抽象化したインタフェースを提供するためのソフトウェア。「デバドラ」「ドライバ」とも略される。

一般にバスや通信サブシステムを経由してそこに接続している周辺機器と通信する。プログラムからドライバ内のルーチンを呼び出すと、ドライバが周辺機器に対してコマンドを発行する。周辺機器がドライバに対してデータを送り返してきたら、ドライバは元の呼び出したプログラム内のルーチンを呼び出すなどする。ドライバはハードウェアに依存し、オペレーティングシステム毎に異なる。非同期なハードウェアインタフェースに対応するため、割り込み処理を提供していることが多い。

概要

ワープロソフト表計算ソフトなどのアプリケーションなどが、グラフィックディスプレイ、プリンタ、ネットワークカードなどのデバイスを利用する際、OSが提供する共通化されたAPI(アプリケーション・プログラミング・インターフェイス)によってデバイスの機能を利用できるようにしておく。そして、抽象化されたAPIとハードウェアとの間の対応を、各ハードウェア用のデバイスドライバが受け持つ。

このような仕組みを採用することで、結果的にハードウェアの差異を吸収することができる。ソフトウェアプログラマは、特定のハードウェアに対応する細々としたソフトウェアを書かずとも、APIにあわせたアプリケーションプログラムを作ることで、作成したソフトウェアから不特定多数のハードウェアを利用することができる。

広く共通化が進んだハードウェア(キーボードマウスUSBなど)では、OS内部に標準ドライバが含まれている場合が多い。標準ドライバがサポートしないハードウェアに関しては、一般に、そのハードウェアを提供するメーカが、デバイスドライバを製品にフロッピーディスクCD-ROMで添付するか、あるいはインターネット上で配布する。

APIとの関係

ドライバは、オペレーティングシステム (OS) の一部として機能する。

ユーザプロセスでのAPI呼び出しをきっかけに、ドライバのコードが呼び出される。しかしドライバのコード自身は、ユーザプロセスではなく、カーネルコードの一部として動作する。

上で言う抽象化されたAPIとは、ほとんどの近代的なOSでは、open, read, write, ioctl, close というAPIに統一化されている。歴史的にいうと、これらのAPIは、記憶装置上のファイルにアクセスするためのAPIであるが、これがデバイスに対してもアクセス可能なように拡張された形で提供されているのが、一般的な作りである。すなわち、デバイスに対して、入出力の準備をするopen処理、デバイスからデータを入力するためのread処理、デバイスにデータを出力するためのwrite処理、デバイスに対して特別な処理を行うためのioctl処理、入出力処理を終えるためのclose処理、などである。

read, writeで実際に何が行われるかは、デバイスごとに異なる。例えば、プリンタに対してwriteを行うと印字されるが、サウンドデバイスに対してwriteを行うと、音が鳴る。マウスに対してreadを行うと、マウスの移動量が読み出せる。デバイスによっては、read, writeの片方にしか意味がない場合も多い。例えば、プリンタに対してreadを行うと、何も行われない場合がほとんどである(紙切れやインク量の状態が読める、という実装もあり得るが)。read, writeでは何もせずに、実際の入出力をioctlだけで行う、という実装も良く用いられる。

内部構成

デバイスドライバの一般的な内部プログラムの構成は、アプリケーションのAPI呼び出しをきっかけに起動されるディスパッチコードと、ハードウェア割り込みにより起動される割り込み処理コード、の2つからなる。 割り込みに対してはさらに、純粋な割り込みルーチンと、OSのタスクスイッチングのタイミングで呼び出される後処理コードの、2段階に分けて実装する作りになっているケースが多い。これは、ハードウェア割り込みルーチンからは、可能な限り早く復帰して欲しいという要望があるため(そうしないと、他のハードウェア割り込みが入れなくなる)、多少時間がかかっても良い処理は、カーネル内で余裕ができたタイミングまで後回しにして実行しよう、という考えに基づいた構成手法である。(後処理コードは、Windowsでは、テンプレート:仮リンク (Deferred Procedure Call) 、Linuxでは、softirqあるいはTaskletと呼ばれる部分に相当する。また、過去のLinuxの実装では、Bottom Halfと呼ばれた部分である。)

最近のOSでは、ハードウェア同士で機能が似たものは、まとめてひとつのクラス(デバイスクラス)として扱う仕組みも存在する。この場合のドライバは階層構造になっており、あるデバイスクラスで共通の処理をする上位ドライバ(クラスドライバ)はOS側で供給され、ハードウェアを提供するメーカでは、下位のドライバを、デバイス個別のミニドライバとして作製する。これにより、ドライバの開発工数を削減できるようになっている。

例えば、シリアルポートではテンプレート:仮リンクのようにシリアルポート全般に共通する標準通信プロトコルに対応する必要がある。これはシリアルポートの論理層(クラスドライバ)で管理することになる。しかし、物理層(ミニドライバ)は特定のシリアルポートのチップと通信できなければならない。16550 UART というハードウェアはPL011[1]とは異なる。物理層はそういったチップ固有の差異に対応している。慣例的に、OSからの要求はまず論理層に対して行われる。そして論理層から物理層が呼び出され、OSの要求をハードウェアが理解できる形にして実行する。逆にハードウェア周辺機器がOSに返答しなければならないとき、まず物理層が対応して論理層を呼び出す。

デバイスドライバがクラスごとに共通化されることで、特定のハードウェアが独自に持っている機能が使えなくなる、あるいは使いにくくなるという欠点もある。新規技術開発で出現したハードウェアでは、その機能をどのようにOSが抽象化するか(クラス化するか)が決まるまで、ミニドライバの開発が待たされることもある。この場合は、ハードウェア毎にネイティブなデバイスドライバを、階層化されないドライバ(モノリシック ドライバ)として作成すれば、早期にドライバを提供することができる。

モノリシックドライバでは、ioctlに、そのハードウェア独自の機能を使うための仕掛けを組み入れることも可能であり、これをあやつる専用のアプリケーションを作れば、さらにきめ細かなハードウェア制御を実現することもできる。

デバイスドライバの内部構造は、OSごとに大きく異なる。

Windowsでは、Windows 98以降、様々なバージョンのWindowsごとにドライバを書く手間を省くために、Win32 ドライバモデル (WDM) アーキテクチャが導入された。 Windowsでは、ドライバの最下層にハードウェアを抽象化する層である Hardware Abstract Layer (HAL) を設けて、プラットホームによる違いを吸収する仕組みも存在する(386, 486, Pentium, Alpha, SPARC, IA-32, IA-64, EM64Tなどといった、CPUの違い、CPUアーキテクチャの進化を吸収する)。

Linux環境では、デバイスドライバをカーネルの一部として構築することもできるし、カーネルとは別のモジュールとして構築することもできる。MakedevにはLinuxでの周辺機器の一覧が含まれており、ttyS(端末)、lp(パラレルポート)、hd(ディスク)、loop(テンプレート:仮リンク)、sound(テンプレート:仮リンクsequencerdsp、audio を含む)など様々な周辺機器が定義されている[2]

ロード可能なデバイスドライバは、Microsoft Windows では ".sys"、Linuxでは ".ko" という拡張子のファイルになっている。この形のデバイスドライバは必要なときだけロードできるという利点があり、カーネルメモリの節約につながる。

以上は、ハードウェアに合わせて、ドライバを各種OSに対して用意するという方針である。これとは逆に、PDAなどの開発現場では、ハードウェアの仕様をできるだけ同じにすることでデバイスドライバの開発の手間を省く、という方針が採用されているケースもある。

開発

デバイスドライバ開発には、そのプラットフォームでのハードウェアとソフトウェアについて詳細まで理解している必要がある。ドライバは高い特権を与えられた環境で動作するので、間違った動作をすると破壊的な結果を招く。対照的に現代のオペレーティングシステムでのユーザーレベルのソフトウェアは、システムの他の部分に影響せずに停止することができる。ユーザーモードで動作するデバイスドライバであっても、バグがあればシステムをクラッシュさせることがある。そういった要因から、問題の診断も困難で危険なものとなる。

したがってドライバを書く仕事は、ハードウェア開発企業のソフトウェア技術者の仕事となることが多い。これは、部外者よりもハードウェア開発元の方がそのデザインに関する情報をより多く得られるためである。さらに言えば、デバイスドライバを提供することで製品を最適な方法で使えることを保証するという意味もある。一般に論理層(クラスドライバ)はOSベンダーが書き、物理層(ミニドライバ)は周辺機器ベンダーが書く。しかし最近では FLOSS OS で使用するためにベンダー以外の者がデバイスドライバを書くことも増えている。その場合、ハードウェア製造業者がその周辺機器のインタフェース仕様について情報を提供することが重要となる。リバースエンジニアリングでそういった情報を解明することもできるが、対応ソフトウェアが全くない状態ではそれも難しくなる。

マイクロソフトは品質の低いデバイスドライバによってシステムの安定性が損なわれるのを防ぐため、ドライバ開発の新たなフレームワーク Windows Driver Foundation (WDF) を開発した。WDFには テンプレート:仮リンク (UMDF) と テンプレート:仮リンク (KMDF) がある。UMDFはユーザーモードで動作するドライバ開発用のフレームワークで、UMDFを使ったユーザーモードのドライバにバグがあったとしても、システム安定性に影響を与えない。KMDFはカーネルモードで動作するデバイスドライバ開発を扱うが、I/O操作のキャンセル、パワーマネジメント、プラグ・アンド・プレイのサポートなど問題を起こしやすい機能の標準的実装を提供している。

アップルOS X 用のドライバ開発のオープンソース・フレームワーク テンプレート:仮リンク を提供している。

カーネルモードとユーザモード

Microsoft Windows では、デバイスドライバはカーネルモードx86 CPU のリング0)またはユーザーモード(x86 CPU のリング3)で動作する[3]。ドライバをユーザーモードで動作させる最大の利点は安定性の向上であり、ユーザーモードのデバイスドライバは品質が悪くてもカーネルメモリを上書きしてシステムをクラッシュさせるということがない[4]。一方、カーネルモードからユーザーモードに移行させると性能が低下するので、性能が要求されるデバイスドライバはユーザーモードに移行できない。

ユーザーモードのモジュールはシステムコールを使わないとカーネル空間にアクセスできない。

仮想デバイスドライバ

仮想デバイスドライバはハードウェア周辺機器をエミュレートするもので、特に仮想化環境で使われる。例えば、Microsoft Windows の動作しているコンピュータ上でDOSプログラムを実行する場合や、Xenなどの上で動作するゲストOSの場合である。ゲストOSがハードウェアと直接やりとりできるようにするのではなく、仮想デバイスドライバがハードウェアをエミュレートすることで、VM内で動作するゲストOS(とその中のデバイスドライバ)が実際のハードウェアにアクセスしているかのような幻影を生じさせる。ゲストOSがハードウェアにアクセスしようとしたとき、ホストOS内の仮想デバイスドライバがそれに対応して呼び出される。仮想デバイスドライバはまた、VM内に割り込みなどのプロセッサレベルのイベントを擬似的に発生させることができる。

仮想化環境以外でも仮想デバイスが使われることがある。例えば、Virtual Private Network では仮想ネットワークカードが使われ、iSCSIでは仮想ディスクデバイスが使われる。仮想デバイスドライバの好例として Daemon Tools などがある。

オープンなドライバ

デバイスドライバ関連のAPIや規格

脚注

テンプレート:Reflist

関連項目

外部リンク

テンプレート:オペレーティングシステム
  1. テンプレート:Cite web
  2. テンプレート:Cite web
  3. テンプレート:Cite web
  4. テンプレート:Cite web
  5. テンプレート:Cite web