Chapter 11. raw デバイス

raw デバイスは、現在あるブロックデバイス(例えばディスク)に接続でき、それらで 「raw(手を加えない)」IO を行うのに利用できます。 このような「raw」IO は、通常ブロックデバイスに通常付属するキャッシュを迂回 します。 したがって raw デバイスは、物理的なデバイスへの経路がより「直結」している ので、アプリケーションからその物理デバイスに対する、IO のタイミングを細かく 制御できます。このため raw デバイスは、自身でキャッシュを持つことが多い データベース管理システムのような、複雑なアプリケーションに適しています。

raw デバイスは、キャラクタデバイス(メジャー番号 162)です。最初のマイナー 番号(つまり 0)は、制御用インタフェースとして予約されていて、普通は /dev/rawctl にあります。raw と呼ばれる ユーティリティ(man rawを参照)は、raw デバイスを 今あるブロックデバイスに接続するのに利用できます。これらの「今あるデバイス」 としては、ディスクや CD-ROM、DVD などのうち、下層のインタフェースが Linux で サポートされている(例えば IDE(ATA)や SCSI)ものが該当します。

私のシステムで実行した下記の一連のコマンドは、まず raw デバイスをリストし、 SCSI ディスクのパーティションを接続し、ついでにディスク全体を接続しています。

$ ls -lR /dev/raw*
crw-r--r--    1 root     root     162,   0 Dec  6 06:54 /dev/rawctl

/dev/raw:
total 0
crw-r--r--    1 root     root     162,   1 Dec  6 06:54 raw1
crw-r--r--    1 root     root     162,   2 Dec  6 06:54 raw2
crw-r--r--    1 root     root     162,   3 Dec  6 06:54 raw3
crw-r--r--    1 root     root     162,   4 Dec  6 06:54 raw4
$
$ raw -qa
$
$ raw /dev/raw/raw1 /dev/sda3
/dev/raw/raw1:  bound to major 8, minor 3
$ raw /dev/raw/raw2 /dev/sda
/dev/raw/raw2:  bound to major 8, minor 0
$ raw -qa
/dev/raw/raw1:  bound to major 8, minor 3
/dev/raw/raw2:  bound to major 8, minor 0

キャラクタデバイス用の通常のシステムコール群は、raw デバイスでも 利用できます。read(2)と write(2)が転送する大きさは、物理的なデバイスブロック サイズの整数倍でなければいけません。これはディスクではセクタの大きさに該当し、 普通は 512 バイトです。read()と write()システムコールに与えられるデータ バッファは、ブロックの大きさに合わせたものでなければいけません。lseek(2) システム・コールも、ファイルの読み書きオフセットをブロックの境界にあわせ なければいけません。pread(3)(man preadを参照)は、 read()と lseek()を兼ね備えたシステムコールで、raw デバイスで便利に使えます (pwrite()も同様)。32 ビットアーキテクチャ (つまり off_t 型が 32 ビット長) で 2 GB(あるいは 4 GB)以上のオフセットを用いる場合には注意が必要です。 解決方法のひとつは、_llseek()システムコールを用いることです (man llseekを参照)。

最近のバージョンの ddlmdd(lmbench に入っているプログラム)のような Unix ユーティリティは、上述のブロックアライン メントを行えるので、「raw」デバイスとデータをやり取りできます。sg_util パッケージに入っている最近のバージョンの sg_dd コマンドは、raw デバイスにも sg デバイスにもアクセスできます。

物理デバイスのセクタ数が奇数だと(blockdev --getsize /dev/raw/raw*)でわかります)、raw 入出力では最後のセクタにアクセス できません。

Warning

あるブロックデバイスに対して、そのデバイスに対応している raw デバイス経由で アクセスし、かつ通常のブロックインタフェース経由でもアクセスすると、2 つの アクセス機構間でキャッシュの一貫性が保てません。例えば /dev/sda1 が両者でマウントされ、接続している raw デバイス 経由でアクセスされると、データに不整合が発生するかもしれません。