Cleaning Up Resources on Module Removal
When you remove a kernel module, it is essential to clean up all resources that were allocated during the module's operation. This process, commonly called resource cleanup, ensures that memory, device registrations, and other kernel resources do not remain allocated after the module is unloaded. Failing to release these resources can lead to memory leaks, dangling device nodes, or even system instability. The kernel expects each module to provide an exit function responsible for undoing everything performed in the initialization phase.
cleanup_module_example.c
12345678910111213141516171819202122232425262728293031323334#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/slab.h> #define DEVICE_NAME "cleanup_demo" static int major; static char *buffer; static int __init cleanup_demo_init(void) { major = register_chrdev(0, DEVICE_NAME, NULL); if (major < 0) return major; buffer = kmalloc(1024, GFP_KERNEL); if (!buffer) { unregister_chrdev(major, DEVICE_NAME); return -ENOMEM; } return 0; } static void __exit cleanup_demo_exit(void) { if (buffer) { kfree(buffer); buffer = NULL; } if (major >= 0) unregister_chrdev(major, DEVICE_NAME); } module_init(cleanup_demo_init); module_exit(cleanup_demo_exit); MODULE_LICENSE("GPL");
Proper cleanup in the module's exit function is critical for system stability. In the code above, the cleanup_demo_exit function frees the memory previously allocated with kmalloc and unregisters the character device from the kernel. This ensures that no memory is leaked and the major number is released, so it can be reused by other drivers or modules. If these steps are skipped, the system may run out of memory over time, or device nodes may remain in /dev, causing confusion and potential conflicts.
remove_device_node_example.c
1234567891011121314151617181920212223242526272829303132333435363738394041#include <linux/module.h> #include <linux/init.h> #include <linux/device.h> #include <linux/fs.h> #define DEVICE_NAME "node_cleanup" static int major; static struct class *cls; static struct device *dev; static int __init node_cleanup_init(void) { major = register_chrdev(0, DEVICE_NAME, NULL); if (major < 0) return major; cls = class_create(THIS_MODULE, "node_cleanup_class"); if (IS_ERR(cls)) { unregister_chrdev(major, DEVICE_NAME); return PTR_ERR(cls); } dev = device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); if (IS_ERR(dev)) { class_destroy(cls); unregister_chrdev(major, DEVICE_NAME); return PTR_ERR(dev); } return 0; } static void __exit node_cleanup_exit(void) { if (!IS_ERR_OR_NULL(dev)) device_destroy(cls, MKDEV(major, 0)); if (!IS_ERR_OR_NULL(cls)) class_destroy(cls); if (major >= 0) unregister_chrdev(major, DEVICE_NAME); } module_init(node_cleanup_init); module_exit(node_cleanup_exit); MODULE_LICENSE("GPL");
Thanks for your feedback!
Ask AI
Ask AI
Ask anything or try one of the suggested questions to begin our chat
Can you explain what happens if the exit function is not implemented correctly?
What are some common mistakes developers make during resource cleanup in kernel modules?
Can you provide an example of a proper exit function for a kernel module?
Awesome!
Completion rate improved to 3.85
Cleaning Up Resources on Module Removal
Swipe to show menu
When you remove a kernel module, it is essential to clean up all resources that were allocated during the module's operation. This process, commonly called resource cleanup, ensures that memory, device registrations, and other kernel resources do not remain allocated after the module is unloaded. Failing to release these resources can lead to memory leaks, dangling device nodes, or even system instability. The kernel expects each module to provide an exit function responsible for undoing everything performed in the initialization phase.
cleanup_module_example.c
12345678910111213141516171819202122232425262728293031323334#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/slab.h> #define DEVICE_NAME "cleanup_demo" static int major; static char *buffer; static int __init cleanup_demo_init(void) { major = register_chrdev(0, DEVICE_NAME, NULL); if (major < 0) return major; buffer = kmalloc(1024, GFP_KERNEL); if (!buffer) { unregister_chrdev(major, DEVICE_NAME); return -ENOMEM; } return 0; } static void __exit cleanup_demo_exit(void) { if (buffer) { kfree(buffer); buffer = NULL; } if (major >= 0) unregister_chrdev(major, DEVICE_NAME); } module_init(cleanup_demo_init); module_exit(cleanup_demo_exit); MODULE_LICENSE("GPL");
Proper cleanup in the module's exit function is critical for system stability. In the code above, the cleanup_demo_exit function frees the memory previously allocated with kmalloc and unregisters the character device from the kernel. This ensures that no memory is leaked and the major number is released, so it can be reused by other drivers or modules. If these steps are skipped, the system may run out of memory over time, or device nodes may remain in /dev, causing confusion and potential conflicts.
remove_device_node_example.c
1234567891011121314151617181920212223242526272829303132333435363738394041#include <linux/module.h> #include <linux/init.h> #include <linux/device.h> #include <linux/fs.h> #define DEVICE_NAME "node_cleanup" static int major; static struct class *cls; static struct device *dev; static int __init node_cleanup_init(void) { major = register_chrdev(0, DEVICE_NAME, NULL); if (major < 0) return major; cls = class_create(THIS_MODULE, "node_cleanup_class"); if (IS_ERR(cls)) { unregister_chrdev(major, DEVICE_NAME); return PTR_ERR(cls); } dev = device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); if (IS_ERR(dev)) { class_destroy(cls); unregister_chrdev(major, DEVICE_NAME); return PTR_ERR(dev); } return 0; } static void __exit node_cleanup_exit(void) { if (!IS_ERR_OR_NULL(dev)) device_destroy(cls, MKDEV(major, 0)); if (!IS_ERR_OR_NULL(cls)) class_destroy(cls); if (major >= 0) unregister_chrdev(major, DEVICE_NAME); } module_init(node_cleanup_init); module_exit(node_cleanup_exit); MODULE_LICENSE("GPL");
Thanks for your feedback!