0

我刚刚开始探索 Linux 字符设备驱动程序。我制作了一个简单的内核模块,我在其中使用 register_chrdev() 函数注册设备。我已将 0 作为参数传递给函数,内核返回给我可用的免费主号码。之后,我使用 mknod 命令创建带有返回的主编号的字符设备文件,并且我成功地做到了。我已经将驱动程序加载到内核中,驱动程序、设备文件和用户空间应用程序之间的通信很好。

问题是当我重新启动系统时,/dev 目录中没有字符设备文件(使用 mknod 创建)。

所以请提出这个问题的解决方案,以便我的字符设备文件即使在重新启动后也会出现在 /dev 目录中。

4

1 回答 1

2

一种解决方案是让您的驱动程序/dev动态创建文件,而不是使用命令创建它们mknod。基本思想是通过调用从你的模块初始化函数创建一个自定义设备类class_create,然后通过调用将设备添加到类中device_create

您需要一个类型的变量struct class *来保存指向自定义类的指针。这个变量需要被模块中的各种函数访问,所以需要在任何函数之外声明,通常这样声明static

static struct class *foo_class;

您的模块初始化函数需要创建类并检查错误:

    foo_class = class_create(THIS_MODULE, "foo");
    if (IS_ERR(foo_class)) {
        /* Failed to create class. */
        rc = PTR_ERR(foo_class);
        goto fail_class_create;
    }

(在这里,goto fail_class_create跳转到一个标签以在返回错误之前清理到目前为止所做的任何事情。如果您不喜欢这种“on error goto”模式,请在返回错误之前随意在此处明确清理。)

如果该class_create函数成功,则应在模块退出函数中不再需要时将其销毁,并且如果模块初始化函数中进一步出现错误,也应作为清理的一部分:

    class_destroy(foo_class);

device_create在创建类时,您可以通过调用创建设备和销毁设备来创建(和销毁)属于该类的设备(我称其为“类设备”)device_destroy。这两个函数都使用设备节点号(主要和次要设备号的组合)来指定要创建或销毁的类设备。例如,可以按如下方式创建类设备:

    struct device *csdev;
    /* ... */
    csdev = device_create(foo_class, hwdev, MKDEV(foo_major, minor), privdata, "foo%u", minor);
    if (IS_ERR(csdev)) {
        /* Failed to create device. */
        rc = PTR_ERR(csdev);
        /* Do any clean-up here. */
    }

(这里,foo_class指向之前创建的自定义类;hwdev指向底层“硬件设备”,NULL如果没有底层硬件设备,则可以设置为;foo_major是您的主要设备号(由 分配register_chrdevminor是设备的次要设备号您要创建的,privdata是一个私有数据指针,通常指向您设备的一些私有数据结构,但也可以是NULL;其余参数由 printf 样式的格式字符串加上格式字符串创建所需的任何额外参数组成设备名称。)

在上面的示例中,如果minor为 0,则设备将动态创建为/dev/foo0.

要销毁设备,请device_destroy按以下方式调用:

    device_destroy(foo_class, MKDEV(foo_major, minor));

(这里,foo_classfoo_majorminor传递给 相同device_create。)

上述函数仅作为 GPL 导出,因此如果您想使用它们,您的模块需要使用以下声明声明其许可证:

MODULE_LICENSE("GPL");
于 2016-09-12T17:34:56.333 回答