過去数回に渡ってLinuxの起動の仕組みを紹介してきました。今回はその最後としてudevとそれが利用するsysfsについて紹介しましょう。udevを使えば,従来はあらかじめ用意しておく必要があったデバイスファイルを必要に応じて動的に作成することができ,周辺機器の活線挿抜などにも,より柔軟に対応することができます。
デバイスファイルとは
コンピュータが機能するためには,ディスプレイやキーボード,ハードディスクなど,さまざまな周辺機器が必要で,これら周辺機器をうまく取り扱うことがOSの重要な仕事になります。Linuxの元となったUNIXでは,さまざまな種類の周辺機器を統一的に扱うために「周辺機器もファイルと同様に扱う」ことにしました。このアイデアを実現するために導入されたのがデバイスファイル(スペシャルファイル)です。
デバイスファイルは,アプリケーションからはファイルと同じように見えますが,これらデバイルファイルへの読み書きは,カーネルが自動的に対応する周辺機器のコマンドに変換して実行します。
デバイスファイルは/devディレクトリに置かれており,ls -lコマンドで見ると,先頭に - が表示される通常ファイルやdが表示されるディレクトリとは異なり,cかbが表示されます。また,ファイルサイズが表示されるべき欄には,サイズではなく2つの数字が並んで表示されます。
# ls -l /dev crw-rw-rw- 1 root root 14, 12 2008-06-29 10:33 adsp crw-rw-rw- 1 root root 14, 4 2008-06-29 10:33 audio .... brw-rw---- 1 root floppy 2, 0 2008-06-29 10:32 fd0 crw-rw-rw- 1 root root 1, 7 2008-06-29 10:32 full crw-rw---- 1 root root 250, 0 2008-06-29 10:32 fw0 brw-r----- 1 root disk 3, 0 2008-06-29 10:32 hda brw-r----- 1 root disk 3, 1 2008-06-29 10:32 hda1 brw-r----- 1 root disk 3, 2 2008-06-29 10:32 hda2 ....
デバイスファイルに付けられた2つの数字は,「(デバイス)メジャー番号」,「(デバイス)マイナー番号」と呼ばれ,メジャー番号でハードウェアの種類を,マイナー番号で同種のハードウェアの中の種類を,それぞれ区別するために使われます。
たとえば上記のデバイスファイルの例では,/dev/hda,/dev/hda1,/dev/hda2はメジャー番号がそれぞれ3で,マイナー番号が0,1,2になっているので,一台目のATA(IDE)ハードディスクはメジャー番号が3,その上のパーティションはそれぞれマイナー番号で区別される(ハードディスク全体はマイナー番号0),ということがわかります。これらメジャー番号,マイナー番号は,カーネルにあらかじめ登録してあるハードウェアの識別番号になります。
デバイスファイルを利用することで,アプリケーションからは/dev/hda1にアクセスすれば,そこに接続されているハードディスクの種類に関わらず,1台目のATA(IDE)ハードディスクの最初のパーティションに対する操作になります。
ATA(IDE)HDDの場合は規格が統一されているのでそれほど問題にはなりませんが,SCSIアダプタ経由で接続するSCSI HDDの場合は,SCSIアダプタごとにコマンド体系が異なっているので, それらをアプリケーションレベルで操作しようとすると大変な作業になります。 そのような手間を隠蔽して,アプリケーションには統一的な方法でハードウェアを利用させることが, カーネルの重要な仕事です。
一方,カーネルの側では,アプリケーションからの/dev/hda1に対する操作は,デバイスファイルの定義によってメジャー番号3,マイナー番号1の周辺機器に対するものと判断され,その識別番号に該当するデバイスドライバに対してコマンドを発行して,実際のハードウェアを操作することになります。
UNIX/Linuxでは,このような仕組みを用いて個別の周辺機器に対する操作を隠蔽し,アプリケーションからは抽象化されたデバイスファイルを操作するだけで周辺機器を扱えるようになっています。
デバイスファイルの仕組みはアプリケーションにとっては便利なものですが,デバイスファイルを経由することに統一した結果,たとえカーネルに認識されていても,デバイスファイルが存在しない周辺機器はアプリケーションから操作することができなくなりました。そのため,従来のUNIX/Linuxでは,カーネルが操作できる(対応している)すべての周辺機器用のデバイスファイルをあらかじめ用意しておく必要がありました。
一方,最近のLinuxカーネルでは前回紹介したようなモジュールドライバの機能を使って,操作できる周辺機器を動的に変更することができるようになり,あらかじめ対応しているすべての周辺機器用のデバイスファイルを用意することは現実的ではなくなりました。また,最近ではUSBやメモリカードなど,動作中に着脱できる周辺機器が増えてきて,その意味からもあらかじめすべてのデバイスファイルを用意することは難しくなってきました。
このような状況を改善するために提案されたのがudevという仕組みです。
udev では,udevdというデーモンがカーネルの内部情報を監視ており,カーネルが新たな周辺機器を検知すれば,その機器に応じたデバイスファイルを動的に作成することができます。最近のLinuxではこの仕組みを用いて,あらかじめすべてのデバイスファイルを用意するのではなく,実際に接続されてカーネルが認識している周辺機器用のデバイスファイルのみを動的に生成できるようになっています。

