Linux cdev和register_chrdev的区别

6

我正在重构一个驱动程序,遇到了LDD3中的cdev接口。阅读过http://lwn.net/Articles/195805/后,我感到更加困惑而不是受益匪浅。从那里的评论中得知:

  • 为了使设备真正出现在文件系统中,您需要调用device_create(class, parent_dev, devno, device_name)
  • 要调用device_create,您需要拥有一个设备类对象:使用现有类之一或使用create_class(THIS_MODULE, class_name)创建自己的类。

我认为这只适用于sysfs。

  1. 因此,新接口是试图改变已失败的东西吗?因此,是否建议继续使用device_create

  2. 如果推荐使用cdev,那么如何创建sysfs条目?

  3. 我从未完全理解拥有设备类的好处,是否有必要拥有设备类,如果有,那么如何使用cdev实现?

1个回答

12

cdev是内核的字符设备表示。一般思路是将cdev与一组file_operations相关联。这些file_operations在设备节点上执行,通常出现在/dev下。使用cdev_init()将与一组file_operations进行关联/链接。最后,在设备上调用cdev_add()使其生效,以便用户可以访问它们。

尽管完成了上述操作,但并不意味着已为您创建了设备节点。这需要手动使用mknod实用程序完成(如LDD3中所解释的那样)。通常情况下,驱动程序应该创建设备节点。使用device_create()函数可实现此目的。设备节点通常与类关联。因此,我们需要首先创建一个类(使用class_create()),然后使用该类创建设备节点。

让我通过一个示例来解释这个问题。只考虑init函数(避免错误处理以保持清晰):

struct class *my_class;
struct cdev my_cdev[N_MINORS];    
dev_t dev_num;

static int __init my_init(void)
{
    int i;
    dev_t curr_dev;

    /* Request the kernel for N_MINOR devices */
    alloc_chrdev_region(&dev_num, 0, N_MINORS, "my_driver");

    /* Create a class : appears at /sys/class */
    my_class = class_create(THIS_MODULE, "my_driver_class");

    /* Initialize and create each of the device(cdev) */
    for (i = 0; i < N_MINORS; i++) {

        /* Associate the cdev with a set of file_operations */
        cdev_init(&my_cdev[i], &fops);

        /* Build up the current device number. To be used further */
        curr_dev = MKDEV(MAJOR(dev_num), MINOR(dev_num) + i);

        /* Create a device node for this device. Look, the class is
         * being used here. The same class is associated with N_MINOR
         * devices. Once the function returns, device nodes will be
         * created as /dev/my_dev0, /dev/my_dev1,... You can also view
         * the devices under /sys/class/my_driver_class.
         */
        device_create(my_class, NULL, curr_dev, NULL, "my_dev%d", i);

        /* Now make the device live for the users to access */
        cdev_add(&my_cdev[i], curr_dev, 1); 
    }

    return 0;
}

现在,我逐个回答你的问题:

那么,新界面是试图改变失败的东西吗?因此推荐继续使用 device_create 吗? 这不是一个新接口。它可以说是一个扩展,通常用于创建设备节点。它还带来了创建 sysfs 属性的优点,这提供了更灵活的访问内核资源的方式。函数device_create()返回指向struct device的指针,在内核中具有非常强大的意义。请查看 LDD3 中关于“Linux 设备模型”的章节。

如果建议使用 cdev,那么如何创建 sysfs 条目? cdev 和 sysfs 条目彼此独立。即使没有 cdev,您也可以创建 sysfs 条目。同样,请查看 LDD3 中关于“Linux 设备模型”的章节。您还可以查看此示例代码以创建 sysfs 条目:http://lxr.free-electrons.com/source/samples/kobject/kobject-example.c

我从来没有真正理解拥有设备类的好处,是否有必要,并且如果有,如何使用 cdev 实现它? 我希望上面的代码回答了这个问题。

通常情况下,您可能根本不会在驱动程序中使用 cdevcdev 是一个非常低级别的表示。使用 cdev 构建了许多强大的设备类型框架,例如输入、tty、ALSA、IIO 等等。所有这些框架都是建立在 cdev 之上的。因此,您可能不会直接使用 cdev。相反,您可以向这些框架注册并以更高效的方式访问设备。向这些框架注册还会为您创建设备节点和 sysfs 条目。

希望这有所帮助。


我遇到这样的情况,我正在运行alloc_chrdev_region两次,就像这样为两个不同的pchannel_p实例alloc_chrdev_region(&pchannel_p-> dev_node,0,1,“dma_proxy”)。 我应该只运行一次,并使用2作为第三个参数,而不是使用1吗? 看起来我注册的第二个设备没有正常工作。 - John Frye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接