一种解决方案是让您的驱动程序/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_chrdev
,minor
是设备的次要设备号您要创建的,privdata
是一个私有数据指针,通常指向您设备的一些私有数据结构,但也可以是NULL
;其余参数由 printf 样式的格式字符串加上格式字符串创建所需的任何额外参数组成设备名称。)
在上面的示例中,如果minor
为 0,则设备将动态创建为/dev/foo0
.
要销毁设备,请device_destroy
按以下方式调用:
device_destroy(foo_class, MKDEV(foo_major, minor));
(这里,foo_class
和foo_major
与minor
传递给 相同device_create
。)
上述函数仅作为 GPL 导出,因此如果您想使用它们,您的模块需要使用以下声明声明其许可证:
MODULE_LICENSE("GPL");