ドライバ - みる会図書館


検索対象: UNIX MAGAZINE 2005年11月号
20件見つかりました。

1. UNIX MAGAZINE 2005年11月号

特集 UN Ⅸデバイスドライバ [ 1 ] 佐島隆博 デバイスドライバの基本概念 この特集では、数回にわたって UNIX におけるデバイ スドライバについて説明する。今回は、デバイスドライバ の基本概念、デバイスの制御に関する一般的な問題点をと りあげる。 カーネル・モジュールのうち、ドライバはハードウェアと 直接かかわる部分である。このため、純粋にソフトウェア 的な論理だけでは説明できないことに出喰わす場合が多い。 ドライノヾのプログラマーはそのたびに回避策を考え、試行 錯誤を繰り返して四苦八苦することになる。そうでなくて も、ドライバは ( ハードウェアとの ) 内輪の決めごとやマジ ックナンバーに満ちた難解な世界である (esoteric という 英単語がよく似合う ) 。 デバイスドライバとは何か 、、デバイスドライバとは何か ? " と訊かれた場合、本誌の読 者ならなんらかの返答はできるだろう。ただし、それぞれ に説明できる範囲や深さは異なるので、まずは基本的な概 念をおさらいしておく。 コンピュータ、とくに人気のない機種は、、ソフトがなけ ればただの箱 " などと揶揄されることがある。言われたほ うはムッとするかもしれないが、よく考えれば、これは真 実を的確にいいあてている。そもそも、コンピュータとい うものは、 CPU や記億装置、入出力装置などの、、デバイ スの集合体 " でしかない。この、、ただの箱 " に有益な仕事 をさせるには、ソフトウェアが必要不可欠である。 コンピュータにソフトウェアを載せる手段は 2 つある。 1 つは、コンピュータに直接アプリケーション・プログ ラムを稼動させることだ。初期のパソコンを使ったことの ある人なら、アプリケーションを切り替えるたびに本体を UNIX MAGAZINE 2005. 11 再起動していたのを思い出すかもしれない。ゲーム機も同 様だし、、、繩ムみコンピュータ " と呼ばれる、特定の用途に 限定したコンピュータでもこの手法を用いている ( その代 表的な例カ甘第若電話である ) 。この方法の長所は、アプリケ ーションがコンピュータのすべての資源を独占できる点に ン、一ドウェアのリソースを最大限に活か ある。つまり、 、、メモリ容量に厳しい制約がある " といった したい " とか、 要求に応えられるのである。 もう 1 つの方法は、コンピュータとアプリケーション のあいだに、、 OS (Operating System)" という管理ソフ トウェアを介在させることだ。 OS があれば、コンピュー タの用途が限定されていない ( 汎用性が求められる ) 場合 や、複数のアプリケーションを同時に稼動させたいとか、あ るいは、アプリケーションを異なるアーキテクチャのハー ドウェアで動かす必要があるといった状況にも対応できる ( 図 1 ) 。 さきほど、、、コンピュータはデバイスの集合体 " だと述べ こでいう、、デバイス " とは CPU やマウス、ネット ワーク・インターフェイスなど、手にとって触れる部品で、 ある程度モジュール化されたものを指す。たとえば、メイ ンメモリとは、個々のメモリ IC ではなく、すべてのメモリ IC と MMU (Memory Management Unit) を組み合わ せたもののことだ。そして、、、デバイスドライバ " とは、 れらのデバイスを直接制御するためのソフトウェアである。 こでは、デバイスドライバとは、コンピュータを、、た だの箱 " 以上のものにするために、 ・ハードウェアにもっとも近いところで動くソフトウェア であることを理解しておこう。そして、デバイスドライバ 17

2. UNIX MAGAZINE 2005年11月号

図 4 メモリからの言蒄入み メモリキャッシュをチェック NO Yes キャッシュにヒット ? メモリから読込み 図 5 メモリへの書込み キャッシュへの書込み 不特定時間の遅延 メモリに反映 キャッシュから読込み ーク・インターフェイスにおいて、受信バケットの到着を 知らせるビットはハードウェアが設疋する。つまり、ドラ イバが使用するメモリ領域において、読込みキャッシュを 使ってはならない、、部分 " ( すべてではない ) があるという ことだ。 次に、メモリへの書込み動作をみてみよう。 図 5 は、一殳に、、ライトバック・キャッシュ (write-back cache)" と呼ばれる方式の概要を示したものだ。書込みデ ータはまずキャッシュに溜められ、その後に変更箇所がま とめてメモリに反映される。ドライバでこの機能が働いて しまうと、 2 つの問題が発生する。 1 つは、ソフトウェア が値を設定してから、その設定が実際に反映されるまでに タイムラグが発生することである。もう 1 つは、ソフトウ ェアの設疋手川頁が害、実に守られる保証がないということだ。 1 つ目の間題は、キャッシュの機能そのものに起因する ので分かりやすい。ある時点でドライバが、 *p = 0X01 ; を実行しても、じつは肝腎のデバイスへの設疋はまだ完了 していない。ところが、ドライバは完了したものとみなし てさきに進むため、デバイスとドライバとのあいだに矛盾 が発生する。 20 2 つ目の問題は、ライトバックの実装によるものだ。メ モリのキャッシュは、、、ページ " と呼ばれる、一定の連続し た領域ごとにおこなわれる。たとえば、 X86 系の CPU で の 1 ページは 4KB である。つまり、メモリは 4KB ( ペ ージ ) 単位で区切られ、キャッシュもページ単位でおこな われる。そして、変更されたキャッシュ内容のライトバッ クもページ単位で、そのコンピュータにとってもっとも効 率のよい方法で実行される。したがって、ドライノヾが、 0x00 ; *p = 0X01 ; のように綿密な手川頁を踏んで設定しても、この手川頁は無視 されてしまう。コンピュータからみれば、該当するべージ を、、べろっ " と一気にプロックライトするほうがはるかに 効率がよいからである。 これで、メモリキャッシュがドライバに悪影響をおよ ばす場合があることは分かったと思う。これを回避するに は、必要に応じてキャッシュを無効にすればよいのだが、具 体的な方法はケースパイケースとしかいいようがない。使 用するコンピュータのアーキテクチャやデバイスの実装方 法、さらに OS によって扱いが異なるからである。 アーキテクチャによっては、コンパイラの最適化のとこ ろでも触れたように、 volatile キーワードの利用で対処で きることもある。これは、 CPU のメモリアクセス命令に、 、キャッシュ有効 " と、、キャッシュ無効 " の 2 つのバージョ ンがある場合だ。 デバイスと CPU とのあいだに高機能な IOMMU (ln- put/Output and Memory Management Unit) カゞ介 在し、ドライバはキャッシュをとくに意識する必要がない 場合もある。 PCI バスなどの汎用パスに接続されるデバイ スは、たいていはこの恩恵に与れる。また、 IOMMU の 設疋を含むカーネルサービスがあれば、ドライバがいちい ち IOMMU に触る必要もない。 さらに、キャッシュの効・無効をアドレス空間で分けて いるアーキテクチャもある。つまり、建前は 32bit アーキ テクチャでも実際には 33bit をもっており、最上位ビット が立っていればキャッシュ無効アクセスとなる、というよ うな手法である。この場合には、ドライバを作成するとき にキャッシュを使うか否かを意識していなければならない。 UNIX MAGAZ 工 NE 2005 . 11

3. UNIX MAGAZINE 2005年11月号

に近い質問を受けるが、答はつねに、、ダメ " である。これは 好き嫌いの問題ではない。 Java は、実行時に JVM (Java (M) という仮想マシ ンが必要だが、カーネル内にそのようなものはない。もと もと JVM は、アプリケーションのアーキテクチャ依存を 回避するための機構なので、ハードウェア・アーキテクチ ャに密着するドライバでは意味がない。また、自動ガべー ジ・コレクションもカーネル内では提供されない。さらに Java でも C 十十でも、実行時には膨大な量のクラスライプ ラリがリンクされる。プログラムの見た目は簡潔であって も、その背後では大勢の黒子力辧な処理をこなしている。 複雑かっオーバーヘッドが大きいので、カーネルのなかに は彼らの居場所がないのである。 今回のまとめ コンピュータは、 、、ソフトがなければただの箱 " である。 この箱に仕事をさせる際、デバイスドライバはハードウェ アともっとも密接にかかわるソフトウェアである。ドライ バをアプリケーションと同列にするか、または垣根を隔て た OS のカーネル内に位置づけるかは一長一短があり、シ ステムの要件によって適切な実装方法も異なる。 通常、何もない状態からプログラムを作成する場合、プ ログラマーには最大限の権限が与えられる。データ構造と その処理手順において、設計と実装の自由裁量カめられ るのだ。しかし、純粋なソフトウェアとは違い、ドライバ の作成ではそう好き勝手にすることはできない。 ドライバ には制御対象となるハードウェアがあり、そのハードウェ アの設計に影響を受けるからだ。この点は、自動車の運転 に似ている。あらかじめ操作手川頁が決められた自動車があ り、運転者はその手川頁を習得しなければならない。 ドライノヾが純粋なソフトウェアではないがゆえに存在す る落し穴もある。代表的な例として、コンパイラの最適化 機能によるコードの省略やメモリキャッシュによる弊害が ある。 こでは紹介しなかったが、ハードウェアにもバグ やリビジョンがあるという点もドライバ特有の落し穴であ ろつ。 落し穴と呼ぶほどではないものの、ドライバでは cptJ とデバイス双方のエンディアンの違い、構造体メンバーの メモリ上の配置、 64bit アーキテクチャにおけるプログラ 28 ミング・モデルの違いなども意識する必要がある。 デバイスの制御自体も、自動車の運転と同じようなもの である。自動車では所定の場所にボタンやレバーカ咐いて おり、運転者はそれらを操作する。一方、デバイス内の所 定の場所にはレジスタがあり、ドライバはそこに数値を書 き込むことで制御をおこなう。 コンピュータ本体とデバイスの接続方法についても述べ た。パフォーマンスや利便性など、追求する目的が異なれ ば、デバイスの接続形態も変わってくる。その影響は、デ バイスとドライバ間のやりとりにもおよぶ。 そして、 DMA と割込みも簡単にまとめたが、この 2 っ はドライパ・プログラミングのなかでも難所となりやすい。 とくに DMA を使う場合はかならす割込みを併用するた め、正確な排他制御カ材く可欠だが、割込み処理とそうでな いときの処理とで混乱しやすい。 これで、基本概念のおさらいは終りである。食傷気味に なったり、話が抽象的すぎてつかみどころがないと感じた 人がいるかもしれない。あえて強調しておくと、これまで に示した内容は基本概念であり、とくに難しいと感じるよ うなものではない。 とはいえ、具体例を示したほうがより深く理解できるだ ろう。そこで、次回は Linux と solaris のネットワーク・ デバイスを例に説明を進めていく。 ( さじま・たかひろ ) UNIX MAGAZINE 2005. 11

4. UNIX MAGAZINE 2005年11月号

特集 UN Ⅸデバイスドライバ [ 1 ] dev-base-addr がデバイスメモリの 0 番地を示してい るとすると、 * p への代入によって LED が点灯し、その後 に消灯することが分かっただろうか。 テパイスドライバならではの落し穴 前節では、ン、一ドウェアの制御はこのようなもの " とい う一例を示した。ある意味ではなんでもありの純粋なソフ トウェア世界の住人にとっては、カルチャー・ショックだ ったかもしれないが、じつはまだまだ序のロである。 さきほどのコードをあらためて眺めてみると、どこか おかしいと思わないだろうか。まず、 *P 変数に連続して 0X01 と Ox00 を書き込んでいる。通常のソフトウェアな ら、たんに 0X00 を書き込むだけであり、このようなプロ グラムはありえない。 LED を点灯、消灯させるという外 部動作をともなうゆえに、一見おかしなプログラムでも省 略してはならないのである。 じつは、ここに第 1 の落し穴が潜んでいる。このプログ ラムをいい加減にコンパイルすると、 LED が点灯しないと いう状態に陥る可能性がある。 ところが、コンパイラはプログラマーが考えていること を推測できない。したがって、この同一変数の二重設定は 、、無駄なコード " とみなさ楸コンパイラの最適化機能によ って排除されてしまうのだ。工ラーや警告などもいっさい 表示されず、プログラムが異常終了するわけではないので、 意図せずにこの状態に陥るとデバッグはひどく難しくなる。 コンパイラが生成したマシンコードを解析して初めて気づ き、、、コンパイラのバグだ ! " と思い込むかもしれない。こ こで重要なのは、 ・最初はコンパイラの最適化機能はすべて無効にしておく ということである。慣れるまではもちろん、新規ドライバ 開発の初期段階ではコンパイラに最適化をさせてはいけな い。多少は実行効率が悪くても、最初のうちはドライノヾ機 能の確認を優先させるべきである。ある程度動くことが分 かってから最適化を有効にしても遅くはないし、それによ りバグが発覚しても、最初につまずくよりは手がかりがあ る。 この問題に対する抜本的な対策は、 C 言語の volatile キ UNIX MAGAZ 工 NE 2005 . 11 ーワードを使うことにつきる。 図 2 メモリアクセス順番の入替え int array [ 4 島 array [ 0 ] array [ 2 ] array [ 1 ] array [ 3 ] 土 n し array [ 4 ] ー array [ 0 ] array [ 1 ] array [ 2 ] array [ 3 ] 連続的にアクセスしたほうが効率がよいと 判断された場合の入替え char array [ 4 ] ー 図 3 複数書込み咲充合 → volatile unsigned char *p = base + 100 ; char *base = dev_base_addr ; と判断された場合の統合 4 バイト書込みのほうが効率がよい 4 つの 1 バイト書込みよりも、 1 つの ☆は n し *)array = 0X00010203 ー char array [ 4 ] ー このようにすれば、 *base と *P の扱いにおいて、コン array [ 0 ] array [ 1 ] array [ 2 ] array [ 3 ] 0X00 ー 0X01 ー 0X02 ー 0X03 ー *p = 0X01 ; *p = 0X00 ; volatile unsigned 19 内容を書き換えることもあるからだ。たとえば、ネットワ ドライバではこの前提は成立しない。デバイスがメモリの 内容を変更するものがなければ、これでよい。ところが、 い場合はメモリから読み込まれる。 CPU 以外にメモリの 図 4 に示したように、キャッシュ内部に該当する値がな まず、メモリからの言囚み動作を検討してみる。 作を妨げるのかを考えてみよう。 モリキャッシュがある。これが、どのようにドライバの動 コンピュータの動作を安価に高速化する技術として、メ 容易に解決できない可能性があり、そのぶん厄介である。 1 つの落し穴がある。これは、ドライパ・プログラマーが 話はここで終りではない。まったく同じところに、もう る現象が異なるので注意が必要だ。 たり ( 図 3 ) する場合もある。これらは、それぞれ目に見え わせて入れ替えたり ( 図 2 ) 、複数の書込みを 1 つにまとめ ほかにもメモリアクセスの順番をコンピュータの都合にあ こでは、最適化の一一例としてコードの省略を挙げたが、 に指定することがたいへん重要である。 ミングでは、最適化してもよい部分とダメな部分を明示的 でもそのままコンパイルしてくれる。ドライバのプログラ パイラは最適化をおこなわず、いくら無駄にみえるコード

5. UNIX MAGAZINE 2005年11月号

特集 図 7 パティング IJN Ⅸテパイスドライバ [ 1 ] 図 6 LittIe Endian と Big Endian Little Endian 1 , 000 番地 1 , 003 番地 工ンティアンとデータ配置 一般的なプログラムでは、データがどのようにメモリ上 に展開されているかを意識することはない。変数に 0X123 45678 という値を設定したとすると、あとでこの変数を参 照したときに 0X12345678 が返ってくればよい。 struct my_structure { Char C ; int i ; Big Endian 1 , 000 番地 1 , 003 番地 という構造体の各メンバー変数が、メモリ上にどのように 配置されるかも気にすることはないだろう。 しかし、ドライバのプログラミングでは重要な要素なの こで触れておく。 で、 int などの多数バイト整数には、 Little Endian と Big Endian という 2 つの十常内方法がある ( 図 6 ) 。 0X12345678 という値が、 int 形式 ( 4 バイト ) で 1 000 ~ 1 , 003 番地に十内されているとしよう。図 6 を見れば一 目瞭然だが、 LittIe Endian と Big Endian では、 0X12 、 0X34 、 0X56 、 0X78 の各バイトの収まる順番カ鼬である。 これが重要になるのは、 CPU とデバイスがアーキテクチ ャ上、異なるエンディアンを使用している場合である。た とえば、 SPARC CPU は Big Endian だが、 PCI ノヾス は LittIe Endian だ。つまり、 SPARC CPU と PCI バスを組み合わせるときには、どちらか ( たいていは CPU 側 ) が相手のエンディアンに合わせてバイト順序を入れ替 えなければならない。 Solaris では、 ddi-put32 (9F) や ddi-get32 (9F) のように、エンディアン変換も含むデー タアクセス・サービスを用意している。 構造体メンバーのメモリ上の配置は、たとえば上の構 造体が 0X3000 番地にあったとすると、 char 変数 c は 0X3000 番地の 1 バイトにある。問題は、その次の int ( 4 UN 工 X MAGAZINE 2005 . 11 struct my structure { Char c; int 土ー バイト ) 変数 i で、これは 0X3004 ~ 0X3007 番地の 4 バ イトに置かれる。つまり、 0X3001 ~ 0X3003 の 3 バイト 、、パディング (padding)" という、箱のなかに商品を は、 固定する詰め物のようなものだ ( 図 7 ) 。 これは、 4 バイト整数は、 0 、 4 、 8 、 12 、 ・・というような 4 の倍数のアドレスに格納するのがもっとも扱いやすいか らである。このような位置を、、 4 バイト境界 (Four-byte Alignment)" と呼ぶ。 short ( 2 バイト ) や long long ( 8 バイト ) の整数も同様である。 ロー 0X3000 番地 char c 0X3004 番地 64bit アーキテクチャ 最近は、パソコンの世界でも 64bit アーキテクチャが普 及しつつある。そのメリットは、アドレス空間が 64bit と なり、大量のメモリが容易に使えることだ。プログラミン グ・モデルとしては、従来の 32bit 環境が ILP32 だった のが、、 LP64 " になった。 ILP と LP は略語で、 I は int 型、 L は long 型、 P は pointer 型のことである。 ILP32 は、 int 型、 long 型と pointer 型が 32bit で表現されることを 意味する。一方、 LP64 は long 型と pointer 型が 64bit になる (int 型は 32bit のまま ) 。 UItraSPARC や AMD Opteron などの 64bit アーキ テクチャは、従来の 32bit アプリケーションの動作にも対 応している。カーネルが LP64 モデルで動いていても、そ の上のアプリケーションは LP64 であったり I わ P32 であ ったりするわけだ ( なお、 ILP32 カーネルの上では LP64 アプリケーションは動かない ) 。このようなアーキテクチ ヤにおいて、 64bit ドライバ ( カーネル内 ) が 32bit アプ リケーションと接触するときは注意が必要である。たとえ ば、 ioctl ( 2 ) の引数として long 型や pointer 型を渡す 際、アプリケーションカ羸疋した 32bit 値を、ドライノヾが 64bit 値として解釈しようとすると言カ作につながる。 このようなドライバでは、アプリケーションが 32bit 、 21

6. UNIX MAGAZINE 2005年11月号

図 8 PCI バスアドレス空間上のデバイスレジスタ PC レヾス 0 アドレス 0X0001 A000 PC レヾス 0 アドレス空間 64bit のどちらのモデルで動いているかを判別し、適切に 対処しなければならない。 デバイスの接続形態による扱い方の違い こまで、、、デバイスの制御は自動車の運転と同じ " と考 え、その例として、 *p = 0X01 ; のようなポインタ変数を使った値の代入を示してきた。っ まり、、、通常のメモリと同じように扱ってきた " わけであ る。 しかし、現実はこれほど一律ではない。もちろん、上記 ことだ。そして、、ネットワーク I / FO " などのバス上のデ のような作法が通用することもあるが、すべてがそうでは バイスは、この空間に自身の制御用ボタンやレバー ない。以下では、この作法が通用する場合としない場合の ジスタ " という ) を配置できる。 それぞれについて、例を挙げながら解説する。 4 のポイントは、 IOMMU が、カーネルアドレス空間と メモリとしてアクセスできる例 : PCI バス接続 PCI アドレス空間を図 9 のように橋渡しすることだ。 テパイス このようにデバイス制御レジスタがカーネルアドレス空 PCI は、さまざまなデバイスを接続するための汎用パス 間に配置されれば、カーネル内から通常のメモリアクセス としてもっとも普及している技術の 1 つだ。 PCI には、以 で操作できる。図 9 の例でいえば、カーネル空間アドレス 下のような特徴がある。 0X35B7F000 はメインメモリの物理アドレス 0X0356500 1. コンピュータ内部における複数デバイスの接続を目的と 0 に、 0X27543000 は PCI バス 0 番のアドレス空間の 0 X0001A000 にそれぞれマッピングされており、アクセス する。 2.32 本または 64 本のアドレスデータ線をもち、高速なデ 時の振分けは IOMMU がおこなっている。また、メイン ータ転送が可能。 メモリへのアクセスにはキャッシュを」にし、 PCI バス 3. 各バスで独自の、、 PCI アドレス空間 " をもち、バス上の へのアクセスにはキャッシュを無効にするのも、 IOMMU デバイスはこの空間の一部を占有できる。 の設疋でおこなう。 4. IOMMU により、 PCI アドレス空間とホスト・コンピュ この概念をさらに一歩進めると、ユーザー空間からの ータ上のアドレス空間とのあいだでマッピングが可能。 デノヾイスの制御が可能になる。 UNIX には mmap(2) というシステムコールがあり、ファイルなどをメモリと 高速なデバイスは、 CPU やメインメモリに近いところ して扱うことができる。ドライバがデバイスレジスタを に配置すれば、より効率的に活用できる。ただし、あまり mmap ( 2 ) でユーザー・プログラムに渡すようにした場合 に近すぎると、用途か特定の CPU やアーキテクチャに限 は、図 10 のような関係になる。 定されてしまう。 PCI バスは、汎用性と効率をバランスよ 動作の原理は、カーネル内にマップした場合と同じで く言妬 t した技術である。 ある。ユーザー・プログラムによるメモリアクセスは、 上記の特徴のなかで、ドライバを作成する側にとってと IOMMU によってメインメモリやデバイスレジスタに振 くに重要なのは 3 番目と 4 番目の点である。 り分けられる。 IOMMU のマッピング設疋は、各仮想ア 3 のポイントは、図 8 のようなことを示す。 ドレス空間のコンテキストの一部である。ユーザープロセ ホスト・コンピュータ上では、カーネルが、、カーネルア スが稼動しているあいだは、そのプロセス用の設疋が適用 ドレス空間 " にさまざまなデータを配置しているが、それと され、カーネルモードに切り替わるとき、コンテキスト・ は別に、各 PCI バスには専用のアドレス空間があるという レ ) ンスタ レンスタ レジスタ PC レヾス 0 22 UNIX MAGAZINE 2005 . 11

7. UNIX MAGAZINE 2005年11月号

c 0 n t e n t s 2 囲 5 / 11 [ 特集 ] UN ー X デバイスドライバ 17 ・・・佐島隆博 デバイスドライバは、ハードウェアともっとも密接にかかわるソフトウェアで あり、一般的なソフトウェアとは異なるさまざまな制約がある。この特集では、 数回にわたり、デバイスドライバの基本概念からプログラミングの手法まで を解説する。今回は、ドライバに特有の“落し穴”やデバイスの制御、デバイ スの接続形態による違いなどについて説明する。 P2P 技術の基礎知識 大谷弘喜 実用的な P2P アプリケーションの一例として、ネットワーク環境を前提とした プロジェクト管理ソフトウェアを紹介する。とくに、その基盤でもあるフレー ムワーク上でのリソースの同期およびノード間連携について、ノード選択の アルゴリズムや実装上のさまざまな工夫などを解説する。 70 UNIX Communication Notes ・・・・・・山口英 データを守る ネットワークとセキュリティ・・・・・・白畑真 RANC 旧ーーーネットワークの設定履歴管理ツール 旧 v6 の実装・・・・・・島慶ー ルータ通知の受信とプレフィックス管理 ネットワーク・ミニ実験室・・・・・・荒井美千子 サブドメインの管理 天文学と UN Ⅸ・・・ 台坂博 PC クラスタ天の川零号機を作る 国立天文台のネットワーク・・・・・・大江将史 続・機内でインターネットーーー CBB 編 プログラミング・テクニック・・・・・・多治見寿和 newsyslog プログラム Pe 活用のヒント 今津英世 genhtpg—PerI による HTML 処理 COVER, CONTENTS DESIGN ・ MORIYA, KAZUO (AUDREY THE DESIGN) 9 3 2 0 4 3 0 8 2 3 4 5 6 8 9 9 第 气

8. UNIX MAGAZINE 2005年11月号

特集 IJN Ⅸテパイスドライバ [ 1 ] 侖をさきにいうと、新たに発行された割込みがより高い優 cache-sync() のような機能の有無は、やはり OS やマ 先度をもっていれば、そちらが優先される。 シン・アーキテクチャ、デバイスの接続形態に依存する。 Solaris の ddi-dma-sync (9F) はこの機能を実現してお 各割込みの優先度はカーネルによってあらかじめ決めら り、呼び出されるたびに同期が必要か否かを判断している。 れており、優先度の高い割込みほど処理の虫さがシビア に要求される。たとえば、シリアルポートの割込み優先度 割込み はかなり高い。なぜなら、シリアルポートで受信したデー タは、案外短い FIFO を通ってくるからだ。すなわち、受 コンピュータの基本動作は、プログラムに言された命 信データを速やかに読み出さないと、あっという間に受信 令を順番に実行していくことだ。この流れを中断させるの FIFO が溢れてしまうのである。 が、文字どおり、、割込み " である。割込みとは、さまざま な外的要因やイベントの発生を CPU に通知する手段であ 高優先度割込みは、その他の処理をすべて停止させるほ る。通知されるイベントは、通信リンクのアップ / ダウン、 どの影響力をもっている。そのため、高優先度割込みの処 データ送受信 DMA 完了、エラーの発生など、多種多様だ。 理は、可能なかぎり簡潔に、かつ自己完結的におこなわな 通常、デバイスの制御は CPU 主導だが、割込みの発行 こで ( 簡潔ではない ) 込み入ったこと ければならない。 に関してはデバイス側に主導権がある。割込みを受け取る をすると、システム全体のパフォーマンスに著しい悪景彡響 と、 CPU はそれまでやっていたことを一時保留し、割込 をおよばす。また ( 自己完結せずに ) 、孑羽也制御など、ほか のリソースに依存することもできるだけ避けなければなら みを処理する。これは、次のような手川頁でおこなわれる。 ない。シリアルポートからの受信による割込み処理は、デ 1. 割込みの発生源を特定 ータをメインメモリ上のバッフアにコピーし、、、ソフトウ ます、どのデバイスから割込みが出ているのかを把握し ェア割込み " の発行を予約するだけだ。ソフトウェア割込 ないとさきに進めない。 みの優先度はハードウェア割込みよりも低いので、システ 2. 割込みを停止する ムへの影響は少ない。こでのポイントは、高優先度で処 デバイスが、、割込みを発行する " というのは、 CPU に対 理する必要がないように、十分な大きさのバッフアをメイ して電気信号を発信することだ。近年のデバイスでは、 ンメモリ上に確保しておくことである。 この信号を CPU 側から停止させる必要がある 1 。これ Linux では、デバイスによる割込みの処理ルーチンと、そ は、、℃ PU が割込みを受け取った " という応答の代わり れに起因するソフトウェア割込みの処理ルーチンを、それ である。ドライバがこの信号を停め忘れると、システム ぞれ Top-half HandIer 、 Bottom-half Handler と呼ぶ。 がハングアップしたような状態に陥る。 SoIaris では、ソフトウェア割込みのことを soft interrupt 3. デバイス内部を調査し、割込みの要因となったイベント と呼んでいる。 を処理する 割込みを発行したデノヾイスが特定できたら、次にそこで ドライバ開発言語 何が起きたかを調べ、その結果に応じた処理をおこなう。 たとえば、、、データ受信完了 " というイベントであれば受 アプリケーション・プログラムの開発には多種多様な手 信処理をおこない、、、ケープルが抜かれた " というのであ 法や言語があり、プログラマーにも言語の好き嫌いがある ればコンソールにその旨を表示し、、、異常が発生 " なら該 だろう。しかし、すくなくとも UNIX 系 OS のドライパ・ 当箇所をリセットする、といったぐあいである。 プログラマーについていえば、誰しも C 言語力野きで、同 時にほかの言語には疎い場合が多い。理由は、ドライノヾの 割込みは通常の処理を一時保留にするが、それでは割込 み処理中に別の割込みが発生したらどうなるだろうか。結 プログラミングでは C とアセンプラしカ駛いものにならな いからだ。 1 ー音 ; の旧いデバイスでは、割込みを電気パルスで示していた。つまり、信号 を一定時間言したあと、自動的にこの信号を消してしまっていた。このタ ときどき、アプリケーション・プログラマーから、「 Java イミングがシビアで、とくに負荷の高いシステムでは割込みの取りこばしカ瀕 を使いたいんだけど」とか「 C 十十、使えますか ? 」と哀願 発した。 一三ロ 27 UNIX MAGAZINE 2005 . 11

9. UNIX MAGAZINE 2005年11月号

写真 1 組み立てたメタルラック 写真 2 スライド式オ胼反 写真 4 ラワン材に印を付ける 写真 7 ラワン材に固定したスペーサー 写真 3 ラワン材とスペーサー 真 4 ) 。だいたいの位置カ哈っていれば、固定には差し支え ありません。 次に、印を付けた場所にドリルで孔をあけます ( 写真 5 ) 。 ドリルのビットは 3mm 径のものを利用しました。板に 対してドリルが垂直になるように、そして、孔が大きくな あまり薄すぎると裏からスペーサーのネジ山カ咄てしまう りすぎないように注意しましよう。このサイズのビットを ので注意しましよう。今回使ったスペーサーは、近くの 使えば、スペーサーをうまいぐあいにねじこむことができ PC ショップで購入したインチタイプです。大雑把にいっ ます ( 写真 6 ) 。 て、 1 台あたり約 20 個のスペーサーが必要でした。ラワ ただ、手で直接ねじこむのはちょっと大変なので、 5mrn ン材は 150 円程度、スペーサーは 10 個で 250 円程度な のソケット・ドライバーを使いました。スペーサーをしっ ので、 1 台あたり 700 円程度で作れます。 かり留めておかないと、マザーボードを取り付けるときに それでは工作を始めましよう。まず、マザーポードと ネジを締めても、下のスペーサーが同時に回転してしまい、 CPU ファンを固定するためのスペーサーの位置決めをし 正しく固定できません。どうしてもスペーサーがうまく固 ます。マザーボードをラワン材の上に置き、固定する位置 定できない場合は、セメダインや木工用ポンドで補強しま になるように調整します。そして、ラワン材の、マザーポー す。これで、ポード部分が完成しました ( 写真 7 ) 。 ドのネジ孔にあたる部分に鉛筆で印を付けていきます ( 写 続いて、この板にマザーポードを固定し、さらに CPU 68 UNIX MAGAZINE 2005. 11

10. UNIX MAGAZINE 2005年11月号

図 12 メインメモリの一部をデバイスアドレス空間にマップする PC レヾス 0 アドレス空間 カーネルアドレス空間 レジスタ レジスタ レ ) ンスタ IOMMU テ / ヾイス デノヾイス PC レヾス 0 PC レヾス 1 デノヾイス メインメモリ しかし、ドライバが通常使っているポインタ ( 図 11 の例 果しか得られないのは、容易に察しがっくだろう。 では *buf と *rcvbuf) は、カーネル空間でのみ効な値 しかし、今回の焦点はメインメモリである。この領域で だ。デバイスに DMA をさせるには、これをデバイスアド はデータ変換やヘッダの追加などの重い処理が入るかもし レス空間上の値に変換しなければならない。この変換作業 れないので、できればメモリキャッシュを活用したい。ま をおこなうのが kern-to-devas() 関数である。 た、 DMA ではある程度まとまった量のデータをやりと りするため、すべての書込みがライトバックで待たされる kern-to-devas() 関数は架空のものだが、実際の奐手 と、パフォーマンスに影響をおよばすかもしれない。さい 順は OS やマシン・アーキテクチャ、デバイスの接続バス形 わい、デバイスレジスタのようにそれぞれのアクセスのタ 態などによって異なる。たとえば、 lntel X86 用の Linux イミングを厳密に守る必要はない。要するに では virt-to-phys() というマクロが用意されていて、使 い方は上記の kern-to-devas() と同じである。一方、 So- ・アクセスの主導権が切り替わる時点で整合性がとれてい laris では DMA 用のメモリの確保 (ddi-dma-mem- ればよい alloc(9F)) や管理のための専用サービスがあり、使い方は いささかネ礬隹になっている。 のである。 CPU が書込みをおこなったら、デバイスがんし そして、もう 1 つの不明要素として cache-sync() 関数 みにくる直前に同期をとる。デバイスが書込みをしたら、 がある。「デバイスドライバならではの落し穴」の節でメモ CPU で読みにいく直前にキャッシュの内容を無効にする。 たとえば、図 11 の最後で受信を有効にしているが、その後、 リキャッシュの弊害について述べたが、これは DMA 用の メモリについてもいえる。 CPU が書き込んだ清報がキャ 実際にデータ受信がおこなわれたら、 cache-sync() をしな ッシュに留まった状態で DMA が実行されると間違った結 ければならない。 26 UNIX MAGAZINE 2005 . 11