多设备驱动:一个驱动模块同时创建3个相同的字符设备

概述

在Linux内核驱动开发中,有时我们需要一个驱动模块管理多个相同的设备。本章将介绍如何编写一个驱动模块,同时创建3个相同的字符设备(如 /dev/vdev0, /dev/vdev1, /dev/vdev2)。

驱动模块 /dev/vdev0 /dev/vdev1 /dev/vdev2

关键概念

实现步骤

  1. 定义设备数量常量(如3个设备)。
  2. 使用 alloc_chrdev_region 动态分配主设备号。
  3. 为每个设备分配一个 cdev 结构体。
  4. 初始化每个 cdev 结构体,关联文件操作函数集。
  5. 使用 cdev_add 将每个设备添加到内核。
  6. /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

测试方法

  1. 编译并加载驱动模块。
  2. 使用 ls -l /dev/vdev* 检查设备节点是否创建成功。
  3. 使用 cat /proc/devices 查看已注册的设备驱动。
  4. 编写测试程序打开这些设备进行读写操作。