The /dev Directory Explained: Device Files, null, zero and random
/dev looks like a directory full of files. Almost nothing in it is a file, nothing in it is stored on your disk, and it is built from scratch every time the machine starts.
What a device file actually is
A device file is a reference to a driver, not a container for data. Opening it connects you to whatever the kernel has registered at that address.
ls -l /dev/null /dev/sda /dev/tty
# crw-rw-rw- 1 root root 1, 3 ... /dev/null
# brw-rw---- 1 root disk 8, 0 ... /dev/sda
# crw-rw-rw- 1 root tty 5, 0 ... /dev/tty
Three things to read there.
The first letter is c or b, the device type.
The two numbers replace the file size. They are the major and minor numbers: major identifies the driver, minor identifies which device that driver is handling. Major 8 is SCSI and SATA disks; minor 0 is the first one.
The group is how access is granted. Membership of disk, video, dialout or input is what makes a device usable without root, which is covered in our users and groups guide.
Block versus character
Block devices are addressed in fixed-size blocks and can be read or written at arbitrary offsets. Disks, partitions, loop devices, LVM volumes. They go through the page cache and the I/O scheduler.
Character devices are streams handled a byte at a time. Terminals, serial ports, audio devices, /dev/null.
lsblk # block devices, as a tree
ls -l /dev/sd* /dev/nvme*
ls -l /dev/tty* | head
The distinction is not cosmetic. You can seek on a block device and mount it; you generally cannot do either with a character device.
The special files worth knowing
# discard anything written here
command > /dev/null 2>&1
# endless zero bytes
dd if=/dev/zero of=file bs=1M count=100
# random bytes
head -c 32 /dev/urandom | base64
/dev/null discards writes and returns end of file on read. It is the bit bucket.
/dev/zero discards writes and returns infinite zero bytes on read. This is the one people reach for when preallocating a file or wiping a device.
The difference catches people out constantly: dd if=/dev/null of=file produces an empty file, because null has nothing to give.
/dev/full is the third of the set. Writes to it fail with ENOSPC, which exists so you can test how a program handles a full disk without filling one.
echo test > /dev/full
# bash: echo: write error: No space left on device
random and urandom
The old advice was that /dev/random is for serious cryptography and /dev/urandom is the convenience version. That has been wrong since Linux 5.6.
Both draw from the same CSPRNG. Once the pool is initialised, which happens early in boot, they behave essentially identically, and urandom never blocks. The blocking behaviour that produced the folklore was removed because it caused real problems: services hanging at boot on machines with little entropy.
Use /dev/urandom, or getrandom() from code. The only case for /dev/random is needing a guarantee that the pool has been initialised, and getrandom() expresses that better.
Terminals, pty and tty
tty # which terminal am I
ls -l /dev/pts/ # pseudo-terminals, one per session
who # who is on which
/dev/tty is a special reference meaning “the terminal of the current process”, which is why it works regardless of which one you are on. /dev/console is the system console. /dev/pts/* are pseudo-terminals, created by terminal emulators and ssh sessions and destroyed when they close.
Writing to another user’s terminal works if permissions allow, which is what wall and write do.
The persistent names are the ones to use
/dev/sda is assigned in detection order. Add a disk, change a controller, boot with a USB stick attached, and yesterday’s sda is today’s sdb.
ls -l /dev/disk/by-uuid/
ls -l /dev/disk/by-id/
ls -l /dev/disk/by-label/
ls -l /dev/disk/by-partuuid/
These are symlinks udev creates from properties of the device itself, so they follow the hardware rather than the boot order.
Use UUIDs in /etc/fstab, always, as our fstab guide covers. A fstab entry referring to /dev/sdb1 is a machine that will eventually fail to boot for a reason that looks unrelated.
by-id is the better choice when you want to identify a specific physical drive, in a mdadm array for example, because it encodes the model and serial.
Nothing here is stored
/dev is devtmpfs, a virtual filesystem living in memory.
mount | grep ' /dev '
# devtmpfs on /dev type devtmpfs (rw,nosuid,...)
The kernel populates it as it discovers hardware. udev then applies rules that create the friendly symlinks, set ownership and permissions, and run helpers.
This is why a device can exist and still be unusable: the node is present because the kernel found the hardware, and the udev rule that would give your user access has not matched. Our udev rules guide covers writing them.
It also means editing anything in /dev is pointless. Change permissions there and they revert on reboot. The fix belongs in a udev rule.
Loop devices and the rest
# mount a disk image as a block device
sudo losetup -fP disk.img
losetup -a
sudo mount /dev/loop0p1 /mnt
# detach
sudo losetup -d /dev/loop0
Loop devices present a regular file as a block device, which is how you mount an ISO or a disk image without writing it to hardware.
Others you will meet:
| Path | What it is |
|---|---|
/dev/mapper/* | LVM volumes and LUKS mappings |
/dev/input/* | Keyboards, mice, controllers |
/dev/dri/* | GPU render and card nodes |
/dev/shm | Shared memory, a tmpfs rather than devices |
/dev/fd | Symlink to the current process’s descriptors |
/dev/dri/renderD128 is the one to check when hardware video acceleration is not working, since a container or user without access to it silently falls back to software.
Things you can actually do with this
Test a disk’s read speed without writing anything:
sudo dd if=/dev/sda of=/dev/null bs=1M count=1024 status=progress
Create a file of a known size:
dd if=/dev/zero of=test.img bs=1M count=512
Check whether your user can reach a device at all:
ls -l /dev/dri/renderD128
id # are you in the render or video group
Find which process is holding a device open:
sudo fuser -v /dev/sdb
sudo lsof /dev/snd/*
That last one answers “the device is busy” far faster than guessing does.
Frequently Asked Questions
What is the difference between a block device and a character device?
A block device is addressed in fixed-size blocks and can be read or written at any offset, which is what disks are. A character device is a stream read or written a byte at a time, which is what terminals, serial ports and /dev/null are. The first letter of ls -l tells you which, b or c.
What is the difference between /dev/null and /dev/zero?
Writing to either discards the data. Reading from /dev/null returns end of file immediately, so it produces nothing. Reading from /dev/zero returns an endless stream of zero bytes. You redirect output to null and you read zeros from zero.
Should I use /dev/random or /dev/urandom?
Use /dev/urandom, or getrandom, on any current kernel. Since Linux 5.6 the two behave almost identically once the pool is initialised, and the old advice that random is somehow stronger reflects a design that no longer exists. urandom never blocks after boot.
Why does /dev/sda sometimes become /dev/sdb after a reboot?
Because kernel device names are assigned in detection order, which is not guaranteed to be stable across boots or hardware changes. Use the persistent symlinks under /dev/disk/by-uuid or by-id in fstab and scripts, because those are derived from the device itself.
Is /dev stored on my disk?
No. On any modern system it is devtmpfs, a virtual filesystem the kernel populates in memory at boot and udev then extends with names, permissions and symlinks. Nothing in it survives a reboot, which is why you cannot fix device problems by editing files there.
What creates the device files in /dev?
The kernel creates the basic nodes through devtmpfs as it discovers hardware. udev then applies rules that add the friendly symlinks, set ownership and permissions, and run helpers. That is why a device can exist while being unusable: the node is there and the udev rule granting you access is not.