the driver model
If every driver invented its own way to register, find its hardware, and clean up, the kernel would be chaos. The driver model is the kernel's shared framework that organizes all drivers, all devices, and the buses connecting them into one consistent system, so a single driver author can plug in and the kernel handles the bookkeeping. Think of it as the company's standard hiring and onboarding process: every specialist (driver) fills out the same forms and gets matched to the right machine (device).
In Linux this is built around three core ideas: a bus (like PCI or USB) that knows how to enumerate devices, a device (a discovered piece of hardware), and a driver (code that can handle a class of devices). The model maintains a registry: when a driver registers, it lists the device IDs it supports; when a device appears, the bus core matches it to a driver and calls that driver's probe function. This matching is the heart of the model — probe() is where a driver wakes up, claims its hardware, maps its registers, and registers an IRQ, and remove() is where it lets go. The whole tree of buses, devices, and drivers is mirrored under /sys (sysfs) so userspace can see it.
It matters because it turns hotplug, power management, and reference counting into shared infrastructure rather than per-driver reinvention. When you plug in a USB stick, you are watching the driver model at work: the USB bus enumerates the new device, matches it to the usb-storage driver, calls probe(), and a new disk appears. A common confusion: the driver model is not the same as a single driver — it is the scaffolding all drivers hang on, and getting its hooks (probe, remove, suspend, resume) right is most of what writing a modern driver is about.
// a PCI driver registers what it can handle: static const struct pci_device_id my_ids[] = { { PCI_DEVICE(0x10ec, 0x8168) }, // vendor, device { 0, } }; // when a matching device appears, the core calls my_probe(dev)
A driver declares the (vendor, device) IDs it supports; the bus core does the matching and calls probe().
probe() can be called at any time (hotplug), possibly long after the module loads, and can fail — it must clean up everything it allocated before returning an error, or you leak kernel resources.