Linuxのカーネルの開発に関する世界観(デバイス)です。
自分の書いたブログ「わたしの名はフレイ」2020/06/26より。
実際のところ、カーネルはデバイスコントローラの詳細をデバイスドライバという小さなソフトウェアモジュールによって知っている。
カーネルにおいて、実際のデバイスの詳細を知っているのは、デバイスドライバだけである。
デバイスには、キャラクタ型デバイスとブロック型デバイスがある。
キャラクタ型デバイスは、その時その時の状況を、バイト列(文字列)によって知らせるようなデバイスであり、システムコールのストリームを通じて操作できる。
ブロック型デバイスは、内部にファイルシステムが存在するデバイスであり、ファイル処理APIを通じてアクセスする。
キャラクタ型デバイスは、ランダムアクセス(好きな時に好きな場所のデータを知ること)ができないが、ブロック型デバイスは、ランダムアクセスができる。
自分の書いたブログ「未来のわたしの心より今のあなたへ」2021/03/16より。
一般的なハードウェアデバイスの仕様というのは、とても複雑であり、プログラマがハードウェアデバイスの仕様通り、プログラムを書くというのは、とても現実的ではない。
そのため、OSはデバイスドライバを用意して、ハードウェアデバイスの仕様を抽象化する。
デバイスドライバは、カーネルの共通のAPIで、ハードウェアデバイスを操作する。
デバイスドライバがあることによって、プログラマはシステムコールだけを知っておけば、ハードウェアデバイスの操作はOSがやってくれる。
カーネルもまた、デバイスの操作にデバイスドライバを使い、カーネルの中でハードウェアデバイスの仕様を詳細に知っているのは、デバイスドライバのみである。
(詳しくはオペレーティングシステム―設計と理論およびMINIXによる実装が参考になります。)
BIOSは、起動時に最初に実行されてブートローダを読み込むだけではなく、接続された機器のI/Oを直接操作し、その操作の方法を共通したインターフェースを通じてOSが行うための基本的なI/O操作方式を提供する。
現代的なOSでは、こうしたI/Oの共通インターフェースの提供はデバイスドライバを通じて行うことが多く、BIOSによるI/O操作はあまり行われなくなっている。
デバイスドライバは、この世界にあまたあるハードウェアデバイスそれぞれを共有のインターフェースで操作する仕組みで、デバイスドライバが用意されていないハードウェアについてはOSは操作することができない。Linuxカーネルの大部分のコードはデバイスドライバに充てられている。Linuxはプリンターなど一部のデバイスについては今でもドライバが十分ではなく、プリンターについては「ドライバレス」と呼ばれる新しい仕組みも開発されている。
最近はLinuxカーネルもX11もモジュールを自動でロードするので、自分でデバイスドライバを導入したり設定したりすることは少なくなっている。組み込みシステム向けにLinuxカーネルを使う場合などは、カーネルを手動コンパイルすることで、必要のないモジュールを全て消去できる。また、リアルタイム向けのパッチを当てることで、プリエンティブルなRTOSの機能(要求が起きてからタスクを実行する時間を最短にする)を実現できる。特に自動車などLinux+Pythonの環境を組み込みでも使いたい場合など(人工知能を乗せるなど)の時は、PC向けの要らない機能(デバイスドライバだけではなくファイルシステムなど)は全部消去させることができる。
デバイスドライバには、大きく分けてブロック型デバイスとキャラクタ型デバイスがある。
基本的に、ブロック型デバイスというのは、ハードディスクやCD-ROMのような「データ」を扱うためのもので、キャラクタ型デバイスというのは、モデムやプリンタやキーボードやマウスといった「やり取り」を行うためのもの。
ブロック型とキャラクタ型の違いは、「好きな時に好きなところにアクセスできるかどうか」。
デバイスの種別 | 説明 |
---|---|
ブロック型デバイス | ランダムアクセス(ランダムに前後してデータを読み書き)ができる。 たとえばハードディスクをファイルシステムとしてマウントして利用できる。 |
キャラクタ型デバイス | ランダムアクセスができず、シーケンシャル(順序的)なアクセスだけが可能。 デバイスファイルをストリームの読み書きに使うことができる。 |
また、このどちらにも当たらないネットワークインターフェースのデバイスドライバがある。デバイスファイルからの読み書きはできない。
デバイスドライバによってデバイスがシステムに認識されると、現在のLinuxではudevを用いて/devディレクトリにデバイスファイルが自動作成される。
プログラムがデバイスファイルにアクセスすると、デバイスドライバに対応するI/Oデバイスを用いて、デバイスを直接触ることができる。
ioctl()はシステムコールのひとつで、デバイスドライバをAPIレベルで操作する。スペシャルファイル(特にキャラクタ型デバイスファイル)のファイルディスクリプタと、ioctlリクエスト番号、そして追加的なパラメータを引数に与えることで、デバイスドライバに直接命令やパラメータを渡すことができる。
以下のサイトが参考になります。
Linuxカーネルの公式のデバイスドライバ開発のためのAPIのドキュメントは以下にあります。(英語)
また、書籍は以下がおすすめです。
以下の書籍が参考になります。
MINIX本では、デバイスドライバについて詳細が記述されています。
LVFSはThe Linux Foundationによる再配布可能なファームウェアの提供・更新サービス。
OMG! Ubuntu!によれば、新しくHPから販売されるPop!_OSのLinuxラップトップは、LVFSを用いてファームウェアが更新される。
Linuxにおいて、デバイスドライバがなければハードウェアデバイスは動かない。
open(), close(), read(), write()といった入出力APIが動くのは、裏でそれらに対応するデバイスドライバが存在するおかげである。
ネットワーク通信やプリンターのデバイスドライバも同様。
デバイスドライバを書くことで、デバイスがLinuxで動くようになる。基本的にデバイスドライバがなければ、Linuxにおいてハードウェアデバイスは動かない。
また、GUI環境において、モニター(ビデオカード)や入力デバイスなどはX11でドライバを設定する。X11設定とプログラミングも参照のこと。
2024.09.16
/devディレクトリにあるデバイスファイルは、Linux デバイスファイルを参照のこと。
I/OについてはLinuxカーネル(IO・入出力)も参照のこと。