A raw device can be bound to an existing block device (e.g. a disk) and be used to perform "raw" IO with that existing block device. Such "raw" IO bypasses the caching that is normally associated with block devices. Hence a raw device offers a more "direct" route to the physical device and allows an application more control over the timing of IO to that physical device. This makes raw devices suitable for complex applications like Database Management Systems that typically do their own caching.
Raw devices are character devices (major number 162). The first minor number (i.e. 0) is reserved as a control interface and is usually found at /dev/rawctl. A utility called raw (see man raw) can be used to bind a raw device to an existing block device. These "existing block devices" may be disks or cdroms/dvds whose underlying interface can be anything supported by Linux (e.g. IDE/ATA or SCSI).
A sequence of commands listing the raw devices and then binding a SCSI disk partition followed by binding the whole disk looks like this on my system:
$ 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 |
The normal array of system calls for character devices are available on raw devices. The size of the transfer for read(2) and write(2) must be an integral multiple of the physical device's block size. For a disk this will be its sector size which is normally 512 bytes. The data buffer given to read() and write() system calls must be aligned to the block size. The lseek(2) call needs to align its file read/write offset to a block boundary as well. The pread(3) call (see man pread) combines a read() and a lseek() and can be useful with raw devices (dito with pwrite() ). Care should be taken with offsets greater than 2 GB (or perhaps 4 GB) on 32 bit architectures where the "off_t" type is 32 bits long. One solution is to use the _llseek() call (see man llseek).
Unix utilities such as recent versions of dd and lmdd (from the lmbench suite of programs) can be used to move data to and from "raw" devices as they meet the above-mentioned block alignment requirements. Recent versions of the sg_dd command in the sg_utils package can access both raw and sg devices.
Warning |
If a block device is being accessed via a bound raw device and also via its normal block interface then there is no cache coherency between the two access mechanisms. For example if /dev/sda1 was both mounted and being accessed via a bound raw device then there could be data inconsistencies. |