Linux devices overview

How hardware is presented on a linux system

view on github

Devices types

  • Devices are special files stored in /dev that provide interfaces to the physical hardware

  • There are two main types of devices under all Unix systems, character and block devices

  • character devices

    • Provide unbuffered direct access to the corresponding hardware

    • Reads and writes are always performed synchronously

    • Examples of character devices are :

      path description
      /dev/mem system RAM
      /dev/fb0 graphics card frame buffer
      /dev/sg0 generic SCSI layer
      /dev/input/* input peripherals (keyboard, mouse, etc)
      /dev/tty* native terminals
      /dev/pts* emulated terminals (ssh, etc)
  • block devices

    • Provide buffered/cached access to the corresponding hardware

    • As a result reads and writes can be asynchronous

    • Examples of block devices are :

      path description
      /dev/sda hard disk (SCSI driver)
      /dev/sda1 system boot partition (fat32)
      /dev/sda2 system and data partition (ext4)
      /dev/sda3 swap partition
      /dev/sdb second hard disk (unpartitioned)

Note : in Unix-like systems, devices can exist with no corresponding physical hardware (pseudo-devices)

Hardware discovery and detection

  • The kernel provides an abstract interface to the system hardware through device drivers which implement low-level interactions
  • Device drivers are part of the linux kernel, and make up for more than half of its source code
  • They allow hardware discovery and hardware addition/removal event detection among other things
  • Once a device driver is loaded, the kernel sends hardware events to the userspace daemon udevd which maintains the virtual filesystem mounted at /dev
  • Running programs can then access the hardware through system calls or by reading/writing to the device files

Note : many shell commands are in fact wrappers around system calls

Persistent storage : blocks vs sectors

  • Linux always creates block devices for storage hardware (file systems can only be mounted if they are on a block device)
  • It is important to understand the concept of blocks and sectors and how they relate to block devices :
  1. sector size :

    • it is the minimal number of contiguous bytes that can be read/written on a physical storage disk

      sector size media
      512 bytes HDD
      2048 bytes CD-ROM/DVD-ROM
      4096 bytes SSD/newer HDD (AF - advanced format)
    • it depends on storage media manufacturers

    • each sector stores metadata (address, error correction information, flaw indicator ...) as well as user data

    • AF uses 4096 bytes sectors because of the increase in disks size (less sector metadata to store)

    • for backwards compatibility, AF disks emulate 512 bytes sectors to the operating system (logical vs physical sectors size)

    • if a file does not fill a whole sector, the remainder of the sector will be filled with zeroes

  2. block size :

    • it is the minimal number of contiguous disk sectors that can be read/written when accessing a file system
    • it depends on file system options (for instance in ext4 it is a group of sectors between 1KiB and 64KiB)
    • block size cannot be smaller than the corresponding disk sector size and is often a multiple of it
    • if a file size is not a multiple of the file system block size, its last block will only be partially filled (fragmentation)
  3. related shell commands :

# storage media sector size
sudo fdisk -l /dev/sda | grep "Sector size"

# block device block size
sudo blockdev --getbsz /dev/sda2

# print the number of blocks used by a file or a directory (recursive)
bash -c 'du -a -B "$(stat -f --format="%S" "$0")" "$0"' "$HOME/test.file" | sort -gr

# hex + ASCII dump blocks 65536 to 131072 from /dev/sda2 (4096 equals 0x1000)
# it's funny to scroll down and see your files contents appear on the file system blocks
sudo xxd -c 32 -seek 0x10000000 -l 0x10000000 /dev/sda2 | less

# you can also use the same command to see which blocks contain specific text values
# (remember that utf8 and utf16 are supersets of ASCII ...)
sudo xxd -c 32 -seek 0x10000000 -l 0x10000000 /dev/sda2 | grep confidential

Notes :

  • linux always assume 512 bytes (logical) block size by default regardless of the filesystem block size
  • for example, if the disk uses AF, any non empty file is reported by stat as using at least 8 blocks
  • filesystems with a small block size use space more efficiently, but are slower