在Linux内核驱动开发中,有时我们需要一个驱动模块管理多个相同的设备。本章将介绍如何编写一个驱动模块,同时创建3个相同的字符设备(如 /dev/vdev0
, /dev/vdev1
, /dev/vdev2
)。
/dev/vdev0
)访问设备。alloc_chrdev_region
动态分配主设备号。cdev
结构体。cdev
结构体,关联文件操作函数集。cdev_add
将每个设备添加到内核。/dev
目录下创建设备节点。#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#define DEVICE_NAME "vdev"
#define DEVICE_COUNT 3
static int major;
static struct cdev vdev_cdev[DEVICE_COUNT];
static int vdev_open(struct inode *inode, struct file *file)
{
pr_info("Device opened\n");
return 0;
}
static struct file_operations vdev_fops = {
.owner = THIS_MODULE,
.open = vdev_open,
};
static int __init vdev_init(void)
{
int i;
dev_t dev;
// 动态分配主设备号
if (alloc_chrdev_region(&dev, 0, DEVICE_COUNT, DEVICE_NAME) < 0) {
pr_err("Failed to allocate chrdev region\n");
return -1;
}
major = MAJOR(dev);
for (i = 0; i < DEVICE_COUNT; i++) {
// 初始化每个cdev结构
cdev_init(&vdev_cdev[i], &vdev_fops);
vdev_cdev[i].owner = THIS_MODULE;
// 添加设备到内核
if (cdev_add(&vdev_cdev[i], MKDEV(major, i), 1) < 0) {
pr_err("Failed to add cdev\n");
goto error;
}
// 创建设备节点
device_create(class, NULL, MKDEV(major, i), NULL, "vdev%d", i);
}
pr_info("vdev module loaded with major %d\n", major);
return 0;
error:
for (; i >= 0; i--) {
cdev_del(&vdev_cdev[i]);
}
unregister_chrdev_region(MKDEV(major, 0), DEVICE_COUNT);
return -1;
}
static void __exit vdev_exit(void)
{
int i;
for (i = 0; i < DEVICE_COUNT; i++) {
device_destroy(class, MKDEV(major, i));
cdev_del(&vdev_cdev[i]);
}
unregister_chrdev_region(MKDEV(major, 0), DEVICE_COUNT);
pr_info("vdev module unloaded\n");
}
module_init(vdev_init);
module_exit(vdev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Multiple character devices driver");
注意: 上述代码中省略了部分细节(如错误处理、类的创建等),实际开发中需要完善。
设备名 | 主设备号 | 次设备号 | 设备节点 |
---|---|---|---|
vdev0 | 动态分配 | 0 | /dev/vdev0 |
vdev1 | 动态分配 | 1 | /dev/vdev1 |
vdev2 | 动态分配 | 2 | /dev/vdev2 |
ls -l /dev/vdev*
检查设备节点是否创建成功。cat /proc/devices
查看已注册的设备驱动。