キャラクタデバイス
Claude Code.icon
データをバイトストリーム(1バイトずつの連続した流れ)として扱うデバイス
ブロックデバイスのようなバッファキャッシュを介さず、ユーザ空間とデバイスドライバが直接やり取りする。 基本的な特徴
シーケンシャルアクセス: 基本的に先頭から順に読み書きする(seekできないものが多い)
バッファなし: カーネルのブロックバッファキャッシュを通らない
即時性: 書いたらすぐデバイスに届く、読んだらすぐ返ってくる
代表的なキャラクタデバイス
端末(キーボード入力・画面出力)
システムコンソール
マウス入力
プリンタ
USBデバイス
カーネル内部の仕組み
キャラクタデバイスドライバは file_operations 構造体を実装してカーネルに登録する:
code:c
struct file_operations {
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
int (*open)(struct inode *, struct file *);
int (*release)(struct inode *, struct file *);
long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
// ...
};
ユーザーが read() システムコールを呼ぶと:
code:_
ユーザー空間: read(fd, buf, count)
↓ システムコール
カーネルVFS: fdからfile_operationsを引く
↓
デバイスドライバ: .read() が呼ばれる
↓
ハードウェア(or 擬似デバイスのロジック)
読み書き以外の制御
read/writeだけでは表現できないデバイス固有の操作は ioctl(I/O control)で行う:
code:c
// 端末のウィンドウサイズ取得
struct winsize ws;
ioctl(fd, TIOCGWINSZ, &ws);
// シリアルポートのボーレート設定
struct termios tio;
ioctl(fd, TCGETS, &tio);
ioctlはデバイスごとに独自のコマンドを定義できる汎用的な拡張ポイント。ただし型安全でなく、ドライバごとにバラバラなので「Unixの設計上の妥協点」とも言われる。
「バッファなし」の意味
ブロックデバイスとの決定的な違い:
code:_
ブロックデバイス: ユーザー → ページキャッシュ → I/Oスケジューラ → デバイス
キャラクタデバイス: ユーザー → デバイスドライバ → デバイス
カーネルのページキャッシュやI/Oスケジューラを経由しない。だからリアルタイム性が求められるデバイス(端末、シリアルポート、オーディオ等)に向いている。
seekできるキャラクタデバイス
「シーケンシャルのみ」は原則であって例外もある。/dev/mem(物理メモリ)や /dev/kmem(カーネルメモリ)はキャラクタデバイスだが lseek でランダムアクセスできる。ブロックバッファが不要でも、アドレス指定したい場合にこうなる。