1. Introduction: Object-Oriented Thinking in the Kernel #
Modern Linux treats devices, buses, and drivers using a highly object-oriented architecture. The kernel models system components using reusable abstractions that resemble class inheritance:
- kobject → fundamental building block
- kset → grouping mechanism
- device / driver / bus → higher-level abstractions
- subsystems → real-world peripherals such as PCI, USB, I2C
This design establishes a clean hierarchy that allows the kernel to manage the complexity of heterogeneous hardware in a consistent way.
2. The Foundation: kobject — The Core Kernel Object
#
At the base of Linux’s device model is kobject, a small but crucial structure embedded inside most driver-related data structures. A kobject provides:
- Naming
- Reference counting
- Parent/child hierarchy
- Sysfs linkage
- Type information (
kobj_type)
struct kobject
#
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent; // Parent in the object hierarchy
struct kset *kset;
struct kobj_type *ktype; // Type definition and callbacks
struct kernfs_node *sd; // Sysfs directory entry
struct kref kref; // Reference counting
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};
struct kobj_type
#
This structure defines the behavior of a kobject, including sysfs operations and release logic.
struct kobj_type {
void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops;
const struct attribute_group **default_groups;
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *);
const void *(*namespace)(struct kobject *);
void (*get_ownership)(struct kobject *, kuid_t *, kgid_t *);
};
Together, kobject + kobj_type implement the kernel’s base class pattern.
3. Building Up: Devices, Drivers, and Buses #
From this foundation, Linux constructs the three central abstractions:
struct device— represents a hardware devicestruct device_driver— represents a driver that manages devicesstruct bus_type— represents a physical or logical bus that connects devices and drivers
3.1 struct device — The Universal Device Object
#
Every device in the kernel—from PCI devices to USB endpoints—eventually becomes a struct device.
struct device {
struct device *parent;
struct kobject kobj; // Embedded kobject
const char *init_name;
const struct device_type *type;
struct bus_type *bus; // Bus this device is attached to
struct device_driver *driver; // Bound driver
struct device_node *of_node; // Device Tree node (if applicable)
dev_t devt; // Char/block device number
struct class *class; // Functional grouping (input, net, etc.)
struct klist_node knode_class;
void (*release)(struct device *dev);
};
3.2 struct device_driver — The Driver Abstraction
#
A driver contains probe/remove callbacks and its own embedded kobject.
struct device_driver {
const char *name;
struct bus_type *bus;
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
struct driver_private *p;
};
3.3 struct bus_type — Matching Devices and Drivers
#
The bus provides the matching logic and dispatches probe/remove to the driver.
struct bus_type {
const char *name;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
struct subsys_private *p;
};
Examples of kernel buses:
- PCI
- USB
- I2C
- SPI
- Platform bus
4. Extending the Model: Subsystems and Real Hardware #
Every real hardware subsystem extends the generic device and driver structures by embedding them inside richer, bus-specific structures.
4.1 PCI — struct pci_dev
#
struct pci_dev {
struct list_head bus_list;
struct pci_bus *bus;
struct pci_bus *subordinate;
struct device dev; // Generic device embedded here
};
The kernel uses container_of() macros such as to_pci_dev() to recover the extended structure.
4.2 USB — struct usb_device
#
USB follows the same pattern:
usb_deviceembeds astruct device- Matching happens via USB IDs
- Drivers embed
struct device_driver
4.3 I2C — struct i2c_client
#
I2C devices are represented as:
struct i2c_client {
unsigned short addr;
struct device dev; // Embedded generic device
...
};
Each bus follows the same expansion structure:
- Base object (
device) - Bus-specific extended object (
pci_dev,usb_device,i2c_client) - Bus-specific driver (
pci_driver,usb_driver,i2c_driver) - Containment and inheritance via embedded
kobject
5. Summary: A Unified, Object-Oriented Device Model #
The Linux kernel’s device model provides:
- A consistent framework for representing hardware
- Reusable abstractions (
kobject,kset) - Logical inheritance via embedded structures
- Unified matching logic across PCI, USB, I2C, SPI, etc.
- sysfs exposure of all device relationships
This object-oriented approach allows Linux to support a vast range of peripherals through the same set of abstractions, enabling maintainability, extensibility, and a clear hierarchical view of complex hardware systems.