🐧 Linux 総合学習プラットフォーム
デバイスドライバ実装 ・ 上級

メジャー番号とマイナー番号

デバイスファイルは名前ではなく、2つの番号でカーネル内のドライバと結びつきます。メジャー番号は「どのドライバが担当するか」を、マイナー番号は「そのドライバが扱う何番目の機器か」を表します。ls -l /dev でファイルサイズが出る位置に、カンマ区切りで「メジャー, マイナー」が表示されます。たとえば同じディスクドライバ配下で /dev/sda と /dev/sdb がマイナー番号で区別される、といった具合です。

デバイスファイルは /dev の中にそれぞれ名前を持って並んでいますが、カーネルがそのファイルと担当するドライバを結びつけるとき、頼りにしているのは実は名前ではありません。本当に使われるのは、デバイス番号と呼ばれる2つの数字の組です。ファイル名は、人間が読んで分かりやすいようにつけた目印にすぎず、カーネルの内部では「どのドライバが、どの機器を担当するか」をこの番号で管理しています。ですから、ファイル名を付け替えても番号さえ同じなら同じ機器を指しますし、逆に同じ名前を付けても番号が違えば別物として扱われます。この番号こそが、デバイスファイルとドライバをつなぐ、目には見えない本当の鍵なのです。

メジャー番号 — 担当ドライバを指す

デバイス番号は、メジャー番号とマイナー番号という2つの数字で構成されます。前半のメジャー番号は「どのドライバが担当するか」を表します。ディスクを扱うドライバ、シリアル通信を扱うドライバ、といった具合に、ドライバごとにメジャー番号が割り当てられ、同じメジャー番号を持つデバイスファイルはすべて同じドライバの管轄に入ります。アプリがあるデバイスファイルを開くと、カーネルはまずそのメジャー番号を見て、「この読み書きの要求は、このドライバに渡せばよい」と判断します。会社にたとえるなら、用件を受け付けてどの部署に回すかを決める、担当部署の番号のようなものだと考えると分かりやすいでしょう。

マイナー番号 — 何番目の機器かを指す

後半のマイナー番号は「そのドライバが扱う、何番目の機器か」を表します。1つのドライバが、同じ種類の機器を複数まとめて受け持つことはよくあり、それらを互いに区別するのがマイナー番号の役目です。分かりやすい例がディスクで、同じディスクドライバの配下にある /dev/sda と /dev/sdb は、メジャー番号は同じでありながら、マイナー番号が違うことで「1台目」「2台目」と区別されています。つまり、メジャー番号でまず担当ドライバを選び、続いてマイナー番号でその中の個々の機器を選ぶ——この2段階の指定によって、たくさんの機器を整理して扱えるわけです。部署を選んでから内線番号で個人を呼び出す、という流れに似ています。

ls -l で読み取る

メジャー番号とマイナー番号は、ls -l /dev を実行すれば実際に目で見て確かめられます。普通のファイルでは、所有者やグループの右側にファイルサイズが表示されますが、デバイスファイルでは、ちょうどそのサイズが入る位置に、カンマで区切って「メジャー, マイナー」の2つの番号が並びます。たとえば 8, 0 のように表示されていれば、メジャー番号が8、マイナー番号が0という意味です。ディスクの行をいくつか見比べてみると、メジャー番号は共通のまま、マイナー番号だけが 0、1、2 と変わっていく様子が確認でき、先ほどの「同じドライバの配下を番号で区別する」という説明が、目で見て腑に落ちます。

番号の中身と確認方法

もう少し内側に踏み込むと、デバイス番号は1つの32ビットの値の中に、メジャー番号とマイナー番号が一緒に詰め込まれた形になっています。前半部分がメジャー、後半部分がマイナーに割り当てられ、メジャー番号よりもマイナー番号のほうに広いビット幅が与えられています。これは、ひとつのドライバが受け持つ機器の数を、十分に多く確保できるようにするためです。そのため、ドライバのプログラムでは、2つの番号から1つのデバイス番号を組み立てたり、逆に1つのデバイス番号からメジャー・マイナーを取り出したりする、専用のマクロ(あらかじめ用意された短い命令)が使われます。また、いまシステムの中でどのメジャー番号がどのドライバに使われているかは、/proc/devices というファイルを見れば一覧できます。自作のドライバを組み込んだあとにここをのぞけば、自分のドライバに割り当てられたメジャー番号がいくつなのかを、その場で確かめられます。

番号の割り当てとデバイスファイルの作成

メジャー番号は、昔から決まっている機器に対しては固定の値が使われますが、自作ドライバの場合は、いま空いている番号をその場でカーネルに割り当ててもらう「動的割り当て」が一般的です。番号を自分で固定して決め打ちにすると、他のドライバが使っている番号とぶつかってしまう恐れがあるため、未使用の番号を動的に受け取るほうが安全だからです。そうして手に入れた番号をもとに、対応するデバイスファイルを作ります。デバイスファイルを手作業で作るには mknod というコマンドを使い、ファイル名、キャラクタ型(c)かブロック型(b)かの種別、そしてメジャー番号とマイナー番号を、この順で指定します。たとえば、あるドライバに割り当てられたメジャー番号を /proc/devices で調べ、その番号と、何番目の機器かを示すマイナー番号を mknod に渡してファイルを作る、という流れです。種別に c を選べばキャラクタ型のデバイスファイルが、b を選べばブロック型のデバイスファイルが作られます。こうして番号を与えて作られたファイルが、その番号を通じて目的のドライバと正しく結びつくのです。

実務での位置づけ

現代のシステムでは、機器を挿すたびに udev が適切な番号でデバイスファイルを自動生成してくれるため、日常的に mknod を手で打つ場面はそれほど多くありません。それでも、メジャー番号とマイナー番号の意味をきちんと理解しておくことは欠かせません。なぜなら、デバイスファイルが本当に期待したドライバに結びついているか、複数の機器が正しく区別されているかを調べたいとき、最後の最後で頼りになるのが、この番号だからです。自作したドライバが思うように動かないとき、ls -l /dev で番号を確かめ、それを /proc/devices の内容と突き合わせる——この一手が、原因を切り分けていくときの確かな出発点になります。

この項目に出てくる用語

メジャー番号/マイナー番号めじゃーばんごうまいなーばんごう
デバイスを識別する2つの番号。メジャー=担当ドライバ、マイナー=何番目の機器か。
デバイスファイルでばいすふぁいる
ハードウェアをファイルとして扱うための特殊ファイル。/dev にある。

関連コマンド

lsmknod

▶ 学習アプリでこの続きを学ぶ・演習する