You’ve now seen every layer of the Linux hardware stack. Let’s assemble them into one coherent mental model.
┌─────────────────────────────────────────────────────────────┐
│ Your Python Code │
│ open() read() write() ioctl() mmap() socket() │
└───────────────────────────┬─────────────────────────────────┘
│ system calls (Ring 3 → Ring 0)
┌───────────────────────────▼─────────────────────────────────┐
│ Linux Kernel (Ring 0) │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────────────┐ │
│ │ VFS │ │ Scheduler │ │ Memory Manager │ │
│ └──────┬──────┘ └──────────────┘ └───────────────────┘ │
│ │ │
│ ┌──────▼─────────────────────────────────────────────┐ │
│ │ Filesystem Layer │ │
│ │ ┌────────┐ ┌────────┐ ┌──────┐ ┌──────────┐ │ │
│ │ │ ext4 │ │ sysfs │ │procfs│ │devtmpfs │ │ │
│ │ │ (disk) │ │ (/sys) │ │(/proc│ │ (/dev) │ │ │
│ │ └────────┘ └────────┘ └──────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Device Drivers │ │
│ │ NVMe SATA e1000e i915 cp210x snd_hda ... │ │
│ └──────────────────────┬───────────────────────────────┘ │
│ DMA / MMIO / Interrupts │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ Hardware Buses │
│ │
│ PCIe ──── GPU, NVMe, NIC, Audio │
│ USB ──── Keyboard, Storage, Serial adapters │
│ I2C ──── Sensors, OLED, RTC │
│ SPI ──── Flash, ADC, Display │
│ SATA ──── Hard drives, SSDs │
└─────────────────────────────────────────────────────────────┘
Python → Kernel: Via system calls. Every open(), read(), write() crosses the Ring 3/Ring 0 boundary. Watch them with strace.
Kernel → Filesystems: The VFS routes all file operations. /sys, /proc, /dev are virtual filesystems — no disk involved.
/dev: Device files created by drivers. Major number identifies the driver; minor number identifies the instance. Open them like regular files.
/sys: The kernel’s hardware object model. One directory per device, one file per attribute. Read hardware state; write to control hardware.
/proc: Process information and kernel state. /proc/cpuinfo, /proc/meminfo, /proc/interrupts, /proc/iomem are your hardware inspection tools.
Drivers → Hardware: Drivers use MMIO (read/write device registers like memory), port I/O (legacy), and DMA (hardware writes directly to RAM). Interrupts tell the CPU when hardware needs attention.
udev: The userspace daemon that watches kernel uevents, creates /dev entries, sets permissions, and fires rules. The bridge between hardware events and your system.
When something hardware-related isn’t working, follow this path:
1. Is the hardware physically detected?
→ lspci / lsusb
2. Is there a driver loaded?
→ lspci -k / lsmod / dmesg
3. Is a /dev file created?
→ ls /dev/ / udevadm info
4. Do you have permission?
→ ls -la /dev/device / groups
5. Is the driver working?
→ dmesg -w while testing / journalctl -k
6. Can Python open it?
→ try open("/dev/...") with explicit error handling
After reading this book, the principle “everything is a file” should feel concrete rather than abstract:
# Get CPU temperature — file read
temp = int(Path("/sys/class/thermal/thermal_zone0/temp").read_text()) / 1000
# Monitor USB plug events — file read from a socket-like fd
for event in pyudev.Monitor.from_netlink(context):
print(event.action, event.sys_name)
# Read random bytes from hardware RNG — file read
entropy = open("/dev/urandom", "rb").read(32)
# Control LED brightness — file write
Path("/sys/class/leds/capslock/brightness").write_text("1")
# Read raw keypress events — file read with struct parsing
data = os.read(open("/dev/input/event0", "rb").fileno(), 24)
# Map hardware registers — file mmap
mm = mmap.mmap(open("/sys/bus/pci/devices/0000:00:02.0/resource0", "rb").fileno(), ...)
All of these are the same operation — file I/O — at different levels of the stack.
If this book has made you curious, here are the natural next steps:
Kernel driver development: Learn to write C kernel modules. “Linux Device Drivers” (3rd ed., free online) and the kernel documentation at kernel.org are the canonical resources.
Embedded Linux: Apply these concepts to ARM boards (Raspberry Pi, BeagleBone, RISC-V boards). Device Tree replaces PCI discovery for embedded hardware.
Real-time Linux: Understand PREEMPT_RT, interrupt latency, CPU isolation, and cyclictest for deterministic hardware control.
Performance tuning: Use perf, ftrace, and eBPF to profile hardware interactions and optimize I/O paths.
Hardware security: Understand IOMMU, DMA remapping, PCIe ACS, and why physical access to hardware is equivalent to root access.
The most important tool isn’t a library or a command — it’s curiosity. When you see a file in /sys you don’t recognize, read it. When dmesg shows a line you don’t understand, search it. Every mystery in the /sys and /proc trees has a well-documented answer in the kernel source and documentation.
The hardware is talking. Now you know how to listen.
Previous: Chapter 11 — Practical Examples