Linux – Understanding /dev and Its Subdirectories and Files

devicesfile-descriptorslinux

$ ls -l /dev/stdin /dev/fd/0
lrwx------ 1 tim tim 64 2011-08-07 09:53 /dev/fd/0 -> /dev/pts/2
lrwxrwxrwx 1 root root 15 2011-08-06 08:14 /dev/stdin -> /proc/self/fd/0
$ ls -l /dev/pts/2 /proc/self/fd/0
crw--w---- 1 tim tty  136, 2 2011-08-07 09:54 /dev/pts/2
lrwx------ 1 tim tim     64 2011-08-07 09:54 /proc/self/fd/0 -> /dev/pts/2
  1. I was wondering if all the files under /dev and its subdirectories
    are all file descriptors of devices?
  2. Why are there so many links from each other? For example, /dev/fd/0,
    /dev/stdin, /proc/self/fd/0 are all links to /dev/pts/2.
  3. If l in lrwx------ mean link, what does c in crw--w----
    mean?

Best Answer

Almost all the files under /dev are device files. Whereas reading and writing to a regular file stores data on a disk or other filesystem, accessing a device file communicates with a driver in the kernel, which generally in turn communicates with a piece of hardware (a hardware device, hence the name).

There are two types of device files: block devices (indicated by b as the first character in the output of ls -l), and character devices (indicated by c). The distinction between block and character devices is not completely universal. Block devices are things like disks, which behave like large, fixed-size files: if you write a byte at a certain offset, and later read from the device at that offset, you get that byte back. Character devices are just about anything else, where writing a byte has some immediate effect (e.g. it's emitted on a serial line) and reading a byte also has some immediate effect (e.g. it's read from the serial port).

The meaning of a device file is determined by its number, not by its name (the name matters to applications, but not to the kernel). The number is actually two numbers: the major number indicates which driver is responsible for this device, and the minor number allows a driver to drive several devices¹. These numbers appear in the ls -l listing, where you would normally find the file size. E.g. brw-rw---- 1 root disk 8, 0 Jul 12 15:54 /dev/sda → this device is major 8, minor 0.

Some device files under /dev don't correspond to hardware devices. One that exists on every unix system is /dev/null; writing to it has no effect, and reading from it never returns any data. It's often convenient in shell scripts, when you want to ignore the output from a command (>/dev/null) or run a command with no input (</dev/null). Other common examples are /dev/zero (which returns null bytes ad infinitum) /dev/urandom (which returns random bytes ad infinitum).

A few device files have a meaning that depends on the process that accesses it. For example, /dev/stdin designates the standard input of the current process; opening from has approximately the same effect as opening the original file that was opened as the process's standard input. Somewhat similarly, /dev/tty designates the terminal to which the process is connected. Under Linux, nowadays, /dev/stdin and friends are not implemented as character devices, but instead as symbolic links to a more general mechanism that allows every file descriptor to be referenced (as opposed to only 0, 1 and 2 under the traditional method); for example /dev/stdin is a symbolic link to /proc/self/fd/0. See How does /dev/fd relate to /proc/self/fd/?.

You'll find a number of symbolic links under /dev. This can occur for historical reasons: a device file was moved from one name to another, but some applications still use the old name. For example, /dev/scd0 is a symbolic link to /dev/sr0 under Linux; both designate the first CD device. Another reason for symbolic links is organization: under Linux, you'll find your hard disks and partitions in several places: /dev/sda and /dev/sda1 and friends (each disk designated by an arbitrary letter, and partitions according to the partition layout), /dev/disk/by-id/* (disks designated by a unique serial number), /dev/disk/by-label/* (partitions with a filesystem, designated by a human-chosen label); and more. Symbolic links are also used when a generic device name could be one of several; for example /dev/dvd might be a symbolic link to /dev/sr0, or it might be a link to /dev/sr1 if you have two CD readers and the second one is to be the default DVD reader.

Finally, there are a few other files that you might find under /dev, for traditional reasons. You won't find the same on every system. On most unices, /dev/log is a socket that programs use to emit log messages. /dev/MAKEDEV is a script that creates entries in /dev. On modern Linux systems, entries in /dev/ are created automatically by udev, obsoleting MAKEDEV.

¹ This is actually no longer true under Linux, but this detail only matters to device driver writers.

Related Question