Team BBL
Previous Page Next Page

4.23. Device Special Files

The two fields st_dev and st_rdev are often confused. We'll need to use these fields in Section 18.9 when we write the ttyname function. The rules are simple.

  • Every file system is known by its major and minor device numbers, which are encoded in the primitive system data type dev_t. The major number identifies the device driver and sometimes encodes which peripheral board to communicate with; the minor number identifies the specific subdevice. Recall from Figure 4.13 that a disk drive often contains several file systems. Each file system on the same disk drive would usually have the same major number, but a different minor number.

  • We can usually access the major and minor device numbers through two macros defined by most implementations: major and minor. This means that we don't care how the two numbers are stored in a dev_t object.

    Early systems stored the device number in a 16-bit integer, with 8 bits for the major number and 8 bits for the minor number. FreeBSD 5.2.1 and Mac OS X 10.3 use a 32-bit integer, with 8 bits for the major number and 24 bits for the minor number. On 32-bit systems, Solaris 9 uses a 32-bit integer for dev_t, with 14 bits designated as the major number and 18 bits designated as the minor number. On 64-bit systems, Solaris 9 represents dev_t as a 64-bit integer, with 32 bits for each number. On Linux 2.4.22, although dev_t is a 64-bit integer, currently the major and minor numbers are each only 8 bits.

    POSIX.1 states that the dev_t type exists, but doesn't define what it contains or how to get at its contents. The macros major and minor are defined by most implementations. Which header they are defined in depends on the system. They can be found in <sys/types.h> on BSD-based systems. Solaris defines them in <sys/mkdev.h>. Linux defines these macros in <sys/sysmacros.h>, which is included by <sys/types.h>.

  • The st_dev value for every filename on a system is the device number of the file system containing that filename and its corresponding i-node.

  • Only character special files and block special files have an st_rdev value. This value contains the device number for the actual device.

Example

The program in Figure 4.25 prints the device number for each command-line argument. Additionally, if the argument refers to a character special file or a block special file, the st_rdev value for the special file is also printed.

Running this program gives us the following output:

      $ ./a.out / /home/sar /dev/tty[01]
      /: dev = 3/3
      /home/sar: dev = 3/4
      /dev/tty0: dev = 0/7 (character) rdev = 4/0
      /dev/tty1: dev = 0/7 (character) rdev = 4/1
      $ mount                      which directories are mounted on which devices?
      /dev/hda3 on / type ext2 (rw,noatime)
      /dev/hda4 on /home type ext2 (rw,noatime)
      $ ls -lL /dev/tty[01] /dev/hda[34]
      brw-------  1 root       3,   3 Dec 31  1969 /dev/hda3
      brw-------  1 root       3,   4 Dec 31  1969 /dev/hda4
      crw-------  1 root       4,   0 Dec 31  1969 /dev/tty0
      crw-------  1 root       4,   1 Jan 18 15:36 /dev/tty1

The first two arguments to the program are directories (/ and /home/sar), and the next two are the device names /dev/tty[01]. (We use the shell's regular expression language to shorten the amount of typing we need to do. The shell will expand the string /dev/tty[01] to /dev/tty0 /dev/tty1.)

We expect the devices to be character special files. The output from the program shows that the root directory has a different device number than does the /home/sar directory. This indicates that they are on different file systems. Running the mount(1) command verifies this.

We then use ls to look at the two disk devices reported by mount and the two terminal devices. The two disk devices are block special files, and the two terminal devices are character special files. (Normally, the only types of devices that are block special files are those that can contain random-access file systems: disk drives, floppy disk drives, and CD-ROMs, for example. Some older versions of the UNIX System supported magnetic tapes for file systems, but this was never widely used.)

Note that the filenames and i-nodes for the two terminal devices (st_dev) are on device 0/7the devfs pseudo file system, which implements the /devbut that their actual device numbers are 4/0 and 4/1.

Figure 4.25. Print st_dev and st_rdev values
#include "apue.h"
#ifdef SOLARIS
#include <sys/mkdev.h>
#endif

int
main(int argc, char *argv[])
{

    int         i;
    struct stat buf;

    for (i = 1; i < argc; i++) {
        printf("%s: ", argv[i]);
        if (stat(argv[i], &buf) < 0) {
            err_ret("stat error");
            continue;
         }

         printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_dev));
         if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) {
             printf(" (%s) rdev = %d/%d",
                     (S_ISCHR(buf.st_mode)) ? "character" : "block",
                     major(buf.st_rdev), minor(buf.st_rdev));

         }
         printf("\n");
    }

    exit(0);

}

    Team BBL
    Previous Page Next Page