Registering a Character Device
Before a character device can interact with the Linux kernel, you must register it so the kernel knows how to communicate with your driver. Registering a character device involves reserving a range of device numbers (major and minor), initializing a character device structure, and associating your driver's file operations with that device. This step is essential for allowing user-space programs to access your device through a node in the /dev directory.
char_reg_example.c
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647#include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/cdev.h> #define DEVICE_NAME "mychardev" static dev_t dev_num; // will hold the major and minor number static struct cdev my_cdev; static int __init mychar_init(void) { int result; // Allocate a range of char device numbers result = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME); if (result < 0) { pr_err("Failed to allocate char device region\n"); return result; } // Initialize cdev structure and add it to kernel cdev_init(&my_cdev, NULL); // NULL for file_operations as placeholder my_cdev.owner = THIS_MODULE; result = cdev_add(&my_cdev, dev_num, 1); if (result < 0) { pr_err("Failed to add cdev\n"); unregister_chrdev_region(dev_num, 1); return result; } pr_info("Char device registered: major=%d minor=%d\n", MAJOR(dev_num), MINOR(dev_num)); return 0; } static void __exit mychar_exit(void) { cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1); pr_info("Char device unregistered\n"); } module_init(mychar_init); module_exit(mychar_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Simple Character Device Registration Example");
When registering a character device, you must assign it a unique identifier so the kernel and user-space applications can reference it. This identifier consists of a major number, which identifies the driver associated with the device, and a minor number, which distinguishes between different devices or instances managed by the same driver. In the example above, the alloc_chrdev_region function dynamically allocates a major number and a range of minor numbers. The cdev_init function prepares the character device structure, and cdev_add registers it with the kernel. You can retrieve the assigned major and minor numbers using the MAJOR() and MINOR() macros, which are printed for reference.
char_unreg_example.c
1234567891011121314#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> static dev_t dev_num; static struct cdev my_cdev; static void __exit mychar_exit(void) { cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1); pr_info("Char device unregistered\n"); } module_exit(mychar_exit);
Thanks for your feedback!
Ask AI
Ask AI
Ask anything or try one of the suggested questions to begin our chat
Can you explain the difference between major and minor numbers in more detail?
How do I create a device node in the /dev directory for my character device?
What happens if I don't register my character device properly?
Awesome!
Completion rate improved to 3.85
Registering a Character Device
Swipe to show menu
Before a character device can interact with the Linux kernel, you must register it so the kernel knows how to communicate with your driver. Registering a character device involves reserving a range of device numbers (major and minor), initializing a character device structure, and associating your driver's file operations with that device. This step is essential for allowing user-space programs to access your device through a node in the /dev directory.
char_reg_example.c
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647#include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/cdev.h> #define DEVICE_NAME "mychardev" static dev_t dev_num; // will hold the major and minor number static struct cdev my_cdev; static int __init mychar_init(void) { int result; // Allocate a range of char device numbers result = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME); if (result < 0) { pr_err("Failed to allocate char device region\n"); return result; } // Initialize cdev structure and add it to kernel cdev_init(&my_cdev, NULL); // NULL for file_operations as placeholder my_cdev.owner = THIS_MODULE; result = cdev_add(&my_cdev, dev_num, 1); if (result < 0) { pr_err("Failed to add cdev\n"); unregister_chrdev_region(dev_num, 1); return result; } pr_info("Char device registered: major=%d minor=%d\n", MAJOR(dev_num), MINOR(dev_num)); return 0; } static void __exit mychar_exit(void) { cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1); pr_info("Char device unregistered\n"); } module_init(mychar_init); module_exit(mychar_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Simple Character Device Registration Example");
When registering a character device, you must assign it a unique identifier so the kernel and user-space applications can reference it. This identifier consists of a major number, which identifies the driver associated with the device, and a minor number, which distinguishes between different devices or instances managed by the same driver. In the example above, the alloc_chrdev_region function dynamically allocates a major number and a range of minor numbers. The cdev_init function prepares the character device structure, and cdev_add registers it with the kernel. You can retrieve the assigned major and minor numbers using the MAJOR() and MINOR() macros, which are printed for reference.
char_unreg_example.c
1234567891011121314#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> static dev_t dev_num; static struct cdev my_cdev; static void __exit mychar_exit(void) { cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1); pr_info("Char device unregistered\n"); } module_exit(mychar_exit);
Thanks for your feedback!