I/O デバイスは、下図の USB Drive (USB メモリ等)・Disk (SSD等)・Printer に相当します。

なお、本記事は Linux カーネルの解説のうち7回「I/O デバイス管理」に関する記事です。
- 【Linux カーネル: OS 入門1】OS、カーネルとは
- 【Linux カーネル: OS 入門2】CPU、プロセス管理
- 【Linux カーネル: OS 入門3】メモリ管理
- 【Linux カーネル: OS 入門4】ストレージ管理、ファイル
- 【Linux カーネル: OS 入門5】ファイルシステムの機能
- 【Linux カーネル: OS 入門6】RAID
- 【Linux カーネル: OS 入門7】I/O デバイス管理 ←イマココ
- 【Linux カーネル: OS 入門8】IPC (プロセス間通信)
I/O デバイスとは
I/O デバイスとは、カーネルに対して Input や Output を行うデバイス(ハードウェア)のことです。I/O デバイスは下図の USB Drive(USB メモリ), Disk(SSD), Printer に当たります。

I/O デバイスは次の2種類があります。
- キャラクタデバイス
- ブロックデバイス
デバイスは OS 上ではデバイスファイルとして扱われます。
キャラクタデバイス
キャラクタデバイスとは、1文字(1バイト、1オクテッド)ずつデータを送信するデバイスです。
通常キャラクタデバイスは、ランダムアクセスやバッファをサポートしていないためストリーム処理となります。(前のデータに戻ることができず、再度デバイスから入力する必要があります。)
デバイスの具体的な例を挙げると「キーボード」や「マウス」等です。
ブロックデバイス
ブロックデバイスはブロックサイズ(一定の長さのバイトやビット)ごとにデータを転送するデバイスです。
ブロックデバイスは、メモリのバッファを利用してデータを溜めることで1バイトより大きいサイズのデータを転送可能です。
アドレス指定が可能であり、ファイルシステムを作成してシーケンシャル、ランダムアクセスが可能なことが多いです。
デバイスの具体的な例を挙げると「SSD」・「USB メモリ」・「CD」等です。
デバイスドライバー
デバイスドライバーとは、I/O デバイスをカーネルが処理するためのカーネルモジュールです。デバイスとアプリケーション(User Library)の間にデバイスドライバーを挟むことで、デバイス間の差異を吸収します(A 社の SSD だろうが、B 社の HDD だろうが同じように write()システムコールでデバイスドライバーにアクセス可能)
デバイスドライバーはカーネルモジュール(ソフトウェア)に含まれるため、後から追加でインストールが可能です。
デバイスコントローラー
デバイスコントローラーは、I/O デバイス用のデータ(シリアルビットストリーム)をデバイスドライバー用のデータ(バイトブロック)に変換するインターフェイスです。
デバイスコントローラーはデバイス(ハードウェア)に含まれます。
I/O デバイスの入出力の検出方法
CPU が I/O デバイスを利用するためには、I/O デバイスの入出力の検出する必要があります。I/O デバイスの入出力を検出する方法は次の2つです。
- Polling I/O
- Interrupts I/O
Polling I/O
Poling I/O は CPU 側から I/O デバイスに I/O 処理待ちがあるか確認する方式です。I/O デバイスが処理待ちをして無い場合は、CPU が処理待ちの確認に使った時間が無駄になるため非効率な方式です。
Interrupts I/O(割り込み I/O)
I/O デバイスから CPU に割り込み要求を送信する方式です。CPU は割り込み要求を受信した時、現在のプロセスを保存しデバイスの処理を行います。デバイスの処理が完了すると、保存したプロセスの処理を再開します。
CPU と I/O デバイスの通信

CPU やデバイスコントローラーは共通のバスを利用してデータをやりとりします。
CPU が I/O デバイスとデータをやりとりする方法は次の3つです。
- port-mapped I/O
- Memory-mapped I/O
- Direct memory access (DMA)
port-mapped I/O
port-mapped I/O とは、I/O デバイスに直接バイトの読み書きをする特別な CPU 命令を利用する方式です。
メモリが足りない時代はこちらの方式が使われてました。
Memory-mapped I/O
Memory-mapped I/O とは、I/O デバイスが「CPU の代わりにメモリに割り当てたバッファ」にデータを送信する方式です。メモリにデータの送信が完了するとCPUに割り込み処理が発生し、メモリ上のデータを CPU が処理します。
主にキーボード等の低速デバイスで利用される方式で、メモリにアクセスする通常の CPU 命令を使い回せるため、回路が簡略化されるので安くて速い特徴を持ちます。。
Direct memory access (DMA)
CPU が I/O デバイスにメモリの読み書き権限を付与する方式です。CPU は I/O デバイスのデータ転送「開始時と終了時」のみ関与します。
SSD 等の高速 I/O デバイスでは、Memory-mapped I/O 方式を利用するとバイトを読み書きする度に CPU に割り込みが発生し CPU が他の作業ができなくなるため、こちらの方式が利用されます。
DMA(Direct memory access)コントローラー
CPU が I/O デバイスに読み書きの権限を付与するには、DMA(Direct memory access)コントローラーと呼ばれるハードウェアを利用します。

DMAは以下のステップで I/O デバイスからメモリにデータを転送します。
- デバイスドライバは、ディスクデータをバッファに転送する命令を受け取る
- デバイスドライバーが、ディスクコントローラーにデータをメモリ内のバッファに転送するように命令
- ディスクコントローラーは各バイトをDMAコントローラーに送信
- DMAコントローラはバイトをバッファに転送し、メモリアドレスを増やし、カウンタを減らす
- カウンタがゼロになると、DMAはCPUに割り込み、転送完了を通知
アプリケーションと I/O デバイスの通信
ユーザーアプリケーションと I/O デバイスの通信は以下のとおりです。
- User I/O Libraries(stdio等)でシステムコールを呼び出す
- システムコール(write等)でデバイスドライバーを呼び出す(Kernelモードへ)
- デバイスドライバーがバイトブロックをデバイスコントローラーに送信(Hardwareへ)
- デバイスコントローラーがバイトブロックをシリアルビットストリームに変換
- シリアルビットストリームを元にデバイスが処理を行う

カーネル I/O サブシステム
カーネルは I/O 処理に関連する以下の機能を持ちます。
機能 | 説明 |
---|---|
スケジューリング | プロセスがデバイスを使う順番を決める |
キャッシング | メモリにキャッシュする I/O データを決める |
バッファリング | 異なるデバイス間でデータをやりとりするためにメモリに一時的にデータを保管 |
スプーリング | 低速なデバイスを利用する場合はスプーリングファイルに一時的にデータを溜める |
エラーハンドリング | 保護されたメモリ領域へアクセスした場合のエラーハンドリング |
Linux カーネルの関連記事
Linux カーネル「デバイス管理」に関する説明は以上となります。
Linux カーネル入門記事の続きは、以下をご覧ください。
- 【Linux カーネル: OS 入門1】OS、カーネルとは
- 【Linux カーネル: OS 入門2】CPU、プロセス管理
- 【Linux カーネル: OS 入門3】メモリ管理
- 【Linux カーネル: OS 入門4】ストレージ管理、ファイル
- 【Linux カーネル: OS 入門5】ファイルシステムの機能
- 【Linux カーネル: OS 入門6】RAID
- 【Linux カーネル: OS 入門7】I/O デバイス管理 ←イマココ
- 【Linux カーネル: OS 入門8】IPC (プロセス間通信)