In the Linux kernel driver model, device classes (struct class) organize character and block devices under /sys/class/ and enable udevd to automatically generate corresponding device nodes in /dev/. Understanding how to register custom kernel classes is fundamental to Linux device driver development.
Kernel Module Source Code (Modern Linux 6.x API)
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/device.h>
#define DEVICE_NAME "lynx_dev"
#define CLASS_NAME "lynx_class"
static int major_number;
static struct class *lynx_class = NULL;
static struct device *lynx_device = NULL;
static int __init lynx_init(void) {
// 1. Dynamically allocate major device number
major_number = register_chrdev(0, DEVICE_NAME, NULL);
if (major_number < 0) return major_number;
// 2. Create custom class under /sys/class/lynx_class/
// (Note: Linux 6.4+ class_create takes only the class name string!)
lynx_class = class_create(CLASS_NAME);
if (IS_ERR(lynx_class)) {
unregister_chrdev(major_number, DEVICE_NAME);
return PTR_ERR(lynx_class);
}
// 3. Create device node automatically creating /dev/lynx_dev
lynx_device = device_create(lynx_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);
if (IS_ERR(lynx_device)) {
class_destroy(lynx_class);
unregister_chrdev(major_number, DEVICE_NAME);
return PTR_ERR(lynx_device);
}
pr_info("Module loaded: Created /sys/class/%s and /dev/%s\n", CLASS_NAME, DEVICE_NAME);
return 0;
}
static void __exit lynx_exit(void) {
device_destroy(lynx_class, MKDEV(major_number, 0));
class_destroy(lynx_class);
unregister_chrdev(major_number, DEVICE_NAME);
pr_info("Module unloaded cleanly.\n");
}
module_init(lynx_init);
module_exit(lynx_exit);
MODULE_LICENSE("GPL");
Comments and corrections