Driver Lifecycle
The lifecycle of a character device driver in the Linux kernel involves three critical phases: module initialization, device registration, and cleanup. Properly managing these stages ensures the driver operates reliably and avoids resource leaks. This section outlines the steps and best practices for each phase.
Module Initialization¶
When a module is loaded, the kernel invokes the module_init-marked function. This function must allocate resources, initialize data structures, and register the device. Global variables class and dev are used to ensure accessibility across both module_init and module_exit.
Example:
struct class *class;
dev_t dev;
static int __init my_init(void) {
struct cdev my_cdev;
struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
.write = my_write,
};
// Allocate a dynamic major number
if (alloc_chrdev_region(&dev, 0, 1, "my_device") < 0) {
return -ENOMEM;
}
// Initialize the cdev structure
cdev_init(&my_cdev, &fops);
if (cdev_add(&my_cdev, dev, 1) < 0) {
unregister_chrdev_region(dev, 1);
return -EFAULT;
}
// Create a device class and device node
class = class_create(THIS_MODULE, "my_class");
device_create(class, NULL, dev, NULL, "my_device");
return 0;
}
Key steps:
1. Allocate a major number with alloc_chrdev_region.
2. Initialize the cdev structure with cdev_init.
3. Register the device with cdev_add.
4. Create a sysfs entry using device_create.
Cleanup Procedures¶
On module removal, the module_exit-marked function must un-register the device, release resources, and clean up allocated structures.
Example:
static void __exit my_exit(void) {
// Destroy the device and class
device_destroy(class, dev);
class_destroy(class);
// Remove the cdev and unregister the major number
cdev_del(&my_cdev);
unregister_chrdev_region(dev, 1);
}
Key takeaways¶
- Module initialization uses
module_initto allocate resources and register the device. Global variablesclassanddevensure accessibility across bothmodule_initandmodule_exit. - Device registration requires dynamic major number allocation (
alloc_chrdev_region) andcdev_addfor modern drivers. - Cleanup in
module_exitmust un-register the device, destroy sysfs entries, and release all allocated resources to avoid leaks.