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)

custom_class_module.cc
#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");