1. Introduction

Linux and Unix-like operating systems follow a Filesystem Hierarchy Standard (FHS). The FHS defines the structure of the file system. In other words, it defines the main directories and their contents. One of the most important directories on the system is the /dev/ directory. In this tutorial, we’ll get a deeper understanding of the /dev/ directory and its functions.

2. What Is the Function of the /dev Directory?

The /dev/ directory consists of files that represent devices that are attached to the local system. However, these are not regular files that a user can read and write to; these files are called devices files or special files:

[root@localhost dev]# ls -l
total 0
crw-r--r--. 1 root root     10, 235 Sep 29 12:08 autofs
drwxr-xr-x. 3 root root          60 Sep 29 12:07 bus
lrwxrwxrwx. 1 root root           3 Sep 29 12:10 cdrom -> sr0
drwxr-xr-x. 2 root root        3100 Sep 29 12:10 char
crw-------. 1 root root      5,   1 Sep 29 12:08 console
lrwxrwxrwx. 1 root root          11 Sep 29 12:07 core -> /proc/kcore
drwxr-xr-x. 3 root root          60 Sep 29 12:07 cpu
crw-------. 1 root root     10,  62 Sep 29 12:08 cpu_dma_latency
drwxr-xr-x. 7 root root         140 Sep 29 12:08 disk
brw-rw----. 1 root disk    253,   0 Sep 29 12:08 dm-0
...

Device files are abstractions of standard devices that applications interact with via I/O system calls. The device files that correspond to hardware devices fall into two main categories. Mainly character special files and block special files.

3. What Is the Difference Between Character Special Files and Block Special Files?

Character special files are simple interfaces to character devices. Likewise, block special files are simple interfaces to block devices. The difference between these devices depends on how the operating system reads data off of them. A driver communicates with a character device by sending single characters as data such as bytes. In addition, character devices don’t require buffering when communicating with a driver. On the other hand, a driver accesses data from block devices through a cache. Moreover, a driver communicates with a block device by sending an entire block of data. For example, character devices are sound cards or serial ports, whereas block devices are hard disks or USBs. We identify block and character devices by the letter that appears in front of the permissions. The letter ‘b’ that is displayed in the first column denotes a block device. On the other hand, the letter ‘c’ shown in the first column symbolizes a character device:

[root@localhost dev]# ls -l
total 0
crw-r--r--. 1 root root     10, 235 Sep 16 11:52 autofs
drwxr-xr-x. 2 root root         280 Sep 16 11:52 block
drwxr-xr-x. 2 root root          60 Sep 16 11:52 bsg
drwxr-xr-x. 3 root root          60 Sep 16 11:52 bus
lrwxrwxrwx. 1 root root           3 Sep 16 13:05 cdrom -> sr0
drwxr-xr-x. 2 root root        3100 Sep 16 13:05 char
crw-------. 1 root root      5,   1 Sep 16 11:52 console
lrwxrwxrwx. 1 root root          11 Sep 16 11:52 core -> /proc/kcore
drwxr-xr-x. 3 root root          60 Sep 16 11:52 cpu
crw-------. 1 root root     10,  62 Sep 16 11:52 cpu_dma_latency
drwxr-xr-x. 7 root root         140 Sep 16 11:52 disk
brw-rw----. 1 root disk    253,   0 Sep 16 11:52 dm-0
brw-rw----. 1 root disk    253,   1 Sep 16 11:52 dm-1
brw-rw----. 1 root disk    253,   2 Sep 16 11:52 dm-2

The majority of the devices we see are character or block devices. However, other types of devices exist, such as socket and pipe devices.

4. What Are Pseudo-Devices?

Pseudo-devices don’t correspond to hardware devices. That is to say, they provide several useful functions. For example /dev/random is a function that generates random data. Pseudo-devices are character devices as well. We can tell the difference between pseudo-devices and other character devices using the major number of a device. Furthermore, device drivers associate with a device through a unique value called a major number. A major and minor number appear when running the ls -l command. A comma separates the two numbers. First, there is the major number then comes the minor number. In our case, the driver associated with pseudo-devices is driver 1 since our major number is 1:

[root@localhost dev]# ls -l |grep random
crw-rw-rw-. 1 root root      1,   8 Sep 29 12:08 random

We can also view the major and minor numbers by running stat. These numbers are displayed under device type:

[root@localhost dev]# stat /dev/random
  File: /dev/random
  Size: 0         	Blocks: 0          IO Block: 4096   character special file
Device: 6h/6d	Inode: 10216       Links: 1     Device type: 1,8
Access: (0666/crw-rw-rw-)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:random_device_t:s0
Access: 2021-09-16 11:52:35.644848848 -0400
Modify: 2021-09-16 11:52:35.644848848 -0400
Change: 2021-09-16 11:52:35.644848848 -0400
 Birth: -

Some device files in the /dev/ directory don’t appear as block or character devices. Instead, symbolic links are listed:

[root@localhost dev]# ls -lhaF| grep ^l 
lrwxrwxrwx.  1 root root           3 Sep 17 09:07 cdrom -> sr0
lrwxrwxrwx.  1 root root          11 Sep 17 09:06 core -> /proc/kcore
lrwxrwxrwx.  1 root root          13 Sep 17 09:06 fd -> /proc/self/fd/
lrwxrwxrwx.  1 root root          12 Sep 17 09:06 initctl -> /run/initctl|
lrwxrwxrwx.  1 root root          28 Sep 17 09:06 log -> /run/systemd/journal/dev-log=
lrwxrwxrwx.  1 root root           4 Sep 17 09:06 rtc -> rtc0
lrwxrwxrwx.  1 root root          15 Sep 17 09:06 stderr -> /proc/self/fd/2
lrwxrwxrwx.  1 root root          15 Sep 17 09:06 stdin -> /proc/self/fd/0
lrwxrwxrwx.  1 root root          15 Sep 17 09:06 stdout -> /proc/self/fd/1|

Symbolic links under the /dev directory are there for many reasons. For example, when looking at /dev/stdin, we see that it points to /proc/self/fd/0. This is because the/proc/self directory sits on the /proc filesystem. When a process reads /proc/self,  it gets information about itself using its process id. So the/proc/self directory is a symbolic link as well:

[root@localhost dev]# ls -l /proc/self/fd/0
lrwx------. 1 root root 64 Sep 17 12:02 /proc/self/fd/0 -> /dev/pts/0

The subdirectory ../fd signifies a file descriptor. A file descriptor is a unique reference to a file or input/output (IO) resource. It assists in identifying the file or input/output resource that a process has to work on. For example, the/dev/pts/0 directory exists in memory. The contents under the directory are pseudo-terminals that allow applications to receive input and display output:

[root@localhost pts]# ls -l /dev/pts
total 0
crw--w----. 1 root tty  136, 0 Sep 17 12:33 0
c---------. 1 root root   5, 2 Sep 17 09:06 ptmx

Additionally, another reason for symbolic links under the /dev directory is a name change. Some applications may still reference older names of files hence the use of symbolic links:

[root@localhost dev]# ls -l
total 0
lrwxrwxrwx. 1 root root           3 Sep 17 09:07 cdrom -> sr0

6. Conclusion

In this article, we looked at the /dev directory and the contents that fall under it. We got to understand the different special files and their respective functions. Furthermore, we discussed why some files are implemented as symbolic links. To sum it up, the /dev directory is a vital part of *nix systems. This is because it highlights the architecture of *nix systems, which is “everything is a file”.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.