如何处理主设备号已知、次设备号未知的Linux字符设备
主设备号已知、次设备号未知的字符设备处理方案
针对你不需要为闲置次设备预分配内存的需求,按实际业务场景选择以下实现即可:
场景1:所有次设备逻辑/状态完全共享(适配你的Hello World需求)
如果无论用哪个次设备号打开该设备,行为完全一致,不需要为次设备做独立状态隔离,直接占用整个主设备号的次设备范围即可:
- 注册设备号时直接申请主设备号255下的全部256个次设备号
- 仅初始化1个cdev实例,将其绑定到整个次设备号范围,所有次设备的访问都会路由到同一套操作逻辑,完全无内存浪费。
场景2:不同次设备需要独立状态隔离
如果不同次设备需要单独统计打开次数、存储私有数据,使用按需分配方案即可:
- 预先注册主设备号255的全部256个次设备号,不预分配设备结构数组
- 在open回调中通过
iminor(inode)获取当前打开的次设备号,用指针数组/哈希表存储已分配的次设备结构,首次打开对应次设备时才动态分配结构实例,后续访问直接复用 - 可在release回调中判断次设备的引用计数,引用归0时释放对应结构,最大化内存利用率。
现有代码修正版(适配场景1,满足打开输出Hello World要求)
你的原始代码存在设备号注册与cdev绑定不匹配、内存泄漏、未实现Hello World输出等问题,修正后代码如下:
#include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/slab.h> #include <linux/printk.h> #include <linux/uaccess.h> MODULE_LICENSE("GPL"); static struct _device { size_t openCount, totalDataWritten; struct cdev c_dev; }; static struct _device myDevice; // 直接用全局结构体,不需要动态分配 static const int major = 255; static const char *name = "solution_node"; static int devOpen(struct inode * n, struct file * f) { myDevice.openCount++; pr_info("Hello World\n"); // 打开设备时在内核日志输出Hello World return 0; } static ssize_t devWrite(struct file * n, char const __user * c, size_t size, loff_t *l) { myDevice.totalDataWritten += size; return size; } static ssize_t devRead(struct file *fp, char __user *buf, size_t size, loff_t *off) { char tmpbuf[64]; // 小缓冲直接用栈,避免kmalloc泄漏 int len = snprintf(tmpbuf, sizeof(tmpbuf), "%zu %zu\n", myDevice.openCount, myDevice.totalDataWritten); if (*off >= len) return 0; if (size > len - *off) size = len - *off; if (copy_to_user(buf, tmpbuf + *off, size)) return -EFAULT; *off += size; return size; } static struct file_operations devOPS = { .owner = THIS_MODULE, .open = devOpen, .write = devWrite, .read = devRead, }; static int __init deviceInit(void) { dev_t devID = MKDEV(major, 0); // 注册整个主设备号下的256个次设备号 if (register_chrdev_region(devID, 256, name) != 0) { pr_err("Failed to register chrdev region\n"); return -EIO; } cdev_init(&myDevice.c_dev, &devOPS); myDevice.c_dev.owner = THIS_MODULE; myDevice.openCount = 0; myDevice.totalDataWritten = 0; // 绑定cdev到全部256个次设备 if (cdev_add(&myDevice.c_dev, devID, 256)) { unregister_chrdev_region(devID, 256); pr_err("Failed to add cdev\n"); return -EIO; } return 0; } static void __exit deviceExit(void) { cdev_del(&myDevice.c_dev); unregister_chrdev_region(MKDEV(major, 0), 256); } module_init(deviceInit); module_exit(deviceExit);
内容的提问来源于stack exchange,提问作者WelcomeToMyTutorial
相关产品推荐
相关产品推荐

