Linuxのデバイスファイルに関する世界観です。
Linuxでは、入出力を表現するために、システムに用意されている「デバイスファイル」(スペシャルファイルとも呼ばれる)から、バイト列の読み書きを行うための「ストリーム」をその場その場でつなぐ(生成)ことで行う。
デバイスファイルは特別なファイルで、Linuxではudevのような仕組みを用いて、デバイスファイルを/devディレクトリに動的に作成する。このデバイスファイルは、ファイルやディレクトリを表すブロック型デバイスのファイルシステムであれば、特定のディレクトリに「マウント」した上で使用する。マウスやキーボードなどのキャラクタデバイスであっても、ストリームからバイト列を操作できる。
デバイスファイルにプログラムが直接アクセスした場合、プログラムは対応するI/Oデバイスを用いて、デバイスを直接操作することになる。
UNIXでは、デバイスファイル(スペシャルファイル)という特殊ファイルを用いて、マシンに繋がったハードウェアデバイスにアクセスする。
この時、UNIXでは昔から、マシンに繋がったデバイスに対して、mknodコマンドを用いてデバイスファイルを手動で作成するという、昔ながらの単純なやり方で、ハードウェアデバイスとやり取りする。
つまり、デバイスを使うためには、マシンに繋ぐだけではなく、手動でデバイスファイルを(アクセスするよりも事前に)作成しなければならない。
だが、デバイスファイルの手動管理は、面倒で、手間を取るだけで意味がない。デバイスが利用可能な状態で繋がれていても、デバイスファイルの作成をし忘れたり、メジャー番号やマイナー番号の設定を間違えれば、使うことができない状況に陥る。
デバイスがマシンに繋がれた段階で、自動的にデバイスファイルを作ってくれて、設定や管理も自動で行ってくれるような機構が備わっていると、便利である。
Linux 2.4では、このような声に応えるために、devfsというカーネルレベルでのデバイスファイル自動作成機構を開発した。
だが、devfsはカーネルレベルでの機構であり、ホットプラグデバイスとの相性が悪い。ユーザーが日常使っていて、USBメモリのように頻繁に抜き差しをするホットプラグデバイスのデバイスファイルを自動管理することが難しかった。以前のホットプラグ機構は、/sbin/hotplugを自動実行することで、ホットプラグデバイスを認識していた。
なので、最近のLinuxでは、新しくudevと呼ばれるユーザーレベルでのデバイスファイル自動作成機構が開発された。
最近のLinuxでは、まず、Linuxカーネルがマシンに繋がれているデバイス情報に基づいて、/sysディレクトリに情報を反映する。また、デバイスが繋がれた段階で、udevdに通知を行う。そして、自動的にudevが「udevルール」を参照し、udevがユーザーレベルでデバイスファイルを自動作成する。
udevルールは、デフォルトのルールが/usr/lib/udev/rules.dにあり、管理者が自分で設定するルールが/etc/udev/rules.dにある。
udevは今のカーネル主要メンテナーのGreg KH(グレッグ・クロー=ハートマン)によって開発された。
詳しくは以下を参照のこと。
Linuxファイルシステム階層も参照のこと。
(詳解 Linuxカーネル 第2版を参考に執筆しました。)
デバイスファイルにはキャラクタ型・ブロック型の区別があるが、このほかに2つの属性がある。それがメジャー番号とマイナー番号。
メジャー番号は、デバイスの大まかな種類を決める1~254までの番号。同じメジャー番号であれば、共通のファイル操作のための関数形態を持つ。
マイナー番号は、同じメジャー番号の中で、それぞれの特有のデバイスを判別するための番号。
(詳解 Linuxカーネル 第2版を参考に執筆しました。)
デバイスファイルの例として、
型 | デバイスファイル |
---|---|
ブロック型 | /dev/fd0(フロッピーディスク) /dev/hda1(IDEハードディスク) /dev/sda1(SCSIハードディスク) |
キャラクタ型 | /dev/ttyp0(端末) /dev/console(コンソール) /dev/lp1(プリンタ) /dev/null(NULLデバイス) |
などがある。
2023.01.21編集
デバイスファイルを作成するシステムコールとしては、mknod(2)がある。mknod()を使うことで、C言語のプログラムからデバイスファイルを作成できる。
また、デバイスファイルを作成するコマンドとしてmknodコマンドがある。
mknodコマンドには、デバイスファイルのファイル名、タイプ(bはブロック型、cとuはキャラクタ型、pは名前付きパイプ)、メジャー番号、マイナー番号を指定する。
ls -lを実行した時、パーミッションの一番左にある「b」はブロック型のデバイスファイル、「c」はキャラクタ型のデバイスファイル、「p」は名前付きパイプを意味する。
2023.01.21-22編集
端末のデバイスファイルについては以下の書籍が参考になります。
Linux 端末も参照のこと。
デバイスドライバについては、Linuxカーネル(デバイス)やLinuxカーネル(IO・入出力)を参照のこと。
最近のudevは、systemdに完全に統合されました。
systemd-udevdの挙動については、以下のリンク先が参考になります。
systemdも参照のこと。