Device files
In Linux, hardware appears as files in /dev. Programs read and write devices with the same system calls they use for ordinary files, and the kernel's drivers do the rest.
Devices as files
Following 'everything is a file', most hardware is accessed through device files in /dev. Opening /dev/sda and reading it returns raw disk bytes; writing to a terminal device displays text. Each device file carries a type and a pair of numbers: the major number identifies the driver, and the minor number identifies a specific device the driver manages. ls -l /dev shows them in place of file sizes.
Character and block devices
Character devices transfer data as a stream of bytes without a fixed block structure: terminals (/dev/tty*), serial ports (/dev/ttyS0, /dev/ttyUSB0), sound devices, and input devices. Block devices transfer data in fixed-size blocks with random access and go through the kernel's block layer and caching: disks (/dev/sda, /dev/nvme0n1), partitions, and loop devices. ls -l marks them with c and b.
Special pseudo-devices
Some device files have no hardware behind them. /dev/null discards writes and returns end of file on reads; /dev/zero returns endless zero bytes; /dev/random and /dev/urandom provide cryptographically secure random bytes (on modern kernels they behave almost identically once seeded); /dev/full always reports a full disk, for testing. /dev/tty refers to the current process's terminal.
Terminals and pseudo-terminals
Physical consoles appear as /dev/tty1 and so on. Terminal emulators and SSH sessions use pseudo-terminals: a pair consisting of a controller side, held by the terminal program, and a /dev/pts/N side that the shell sees as its terminal. The tty command prints the current terminal device. The terminal driver handles line editing, echo, and turning Ctrl+C into SIGINT.
Loop devices
A loop device makes an ordinary file behave like a block device, so a disk image or ISO file can be mounted: mount -o loop image.iso /mnt, or losetup to attach a file explicitly. Snap packages on Ubuntu are mounted from loop devices, which is why lsblk on such systems lists many loop entries.
Device permissions
Because devices are files, file permissions control access to hardware. Disk devices are usually owned by root and the disk group, so ordinary users cannot read raw disks; serial ports often belong to the dialout group; sound and video devices may grant access to users at the active console. Adding a user to a group, such as dialout for an Arduino board, grants the corresponding hardware access.
Talking to devices
Besides read and write, programs control devices with ioctl() calls, device-specific commands such as setting a serial port's speed or ejecting a disc. Devices can also be memory-mapped. Higher-level user-space libraries usually wrap these details, such as ALSA or PipeWire for sound, libusb for USB devices, and Video4Linux for cameras.
Worked example
ls -l /dev/sda /dev/tty1 /dev/null might show brw-rw---- 1 root disk 8, 0 /dev/sda, crw--w---- 1 root tty 4, 1 /dev/tty1, and crw-rw-rw- 1 root root 1, 3 /dev/null. The b and c mark block and character devices; 8, 0 means major 8 (SCSI disk driver) and minor 0 (first whole disk); /dev/null is writable by everyone, which is why any user can discard output into it.
Key takeaways
Hardware appears as device files in /dev, with major numbers identifying drivers and minor numbers specific devices. Character devices stream bytes (terminals, serial ports, input); block devices offer random block access through the block layer (disks, partitions, loop devices). Pseudo-devices include /dev/null, /dev/zero, /dev/urandom, and /dev/full. Terminal emulators and SSH use pseudo-terminals under /dev/pts. Loop devices mount image files. File permissions and groups such as disk and dialout control hardware access. ioctl() sends device-specific commands, usually wrapped by libraries such as ALSA, libusb, and Video4Linux.
Flashcard
File in /dev representing hardware
Check your understanding
Why can any user run command > /dev/null, but not read /dev/sda?
