device_create with existing device name
我正在学习如何将字符设备驱动程序编写为Linux的可动态加载的模块。通常,我使用以下函数调用序列来注册设备并创建一个出现在/dev/下的设备文件:
1 2 3 4 5
| alloc_chrdev_region(&first, 0, 1,"myclass");
myclass = class_create(THIS_MODULE,"myclass");
device_create(myclass, NULL, first, NULL,"mydevicefile");
cdev_init(&c_dev, &fops);
cdev_add(&c_dev, first, 1); |
该设备文件然后出现在/dev/mydevicefile上,我可以与它进行交互。
这让我想知道如果传递现有的设备文件名而不是" mydevicefile"会发生什么:
1
| device_create(myclass, NULL, first, NULL,"null"); |
这导致/dev/null被我的字符设备文件替换-还有更多有关的问题:期望原始/dev/null的守护进程在我的控制台中发出了错误消息。甚至没有删除我的人造null模块即可解决此问题。
在实践中,不应该存在与我的模块使用的设备名称相同的现有设备文件,但从理论上讲,可以覆盖另一个设备文件这一事实仍然困扰着我。
如何防止设备文件已经存在与我要使用的文件名相同的情况?
更新:我想我真正想找出的是为什么udev允许替换。
所有设备驱动程序(位于/dev中)基本上都是文件类型,这意味着检查设备文件是否已存在的方式与检查文件是否存在的方式相同。一种方法是使用:
1 2 3 4 5 6 7 8 9 10 11 12
| #include <unistd.h> // for F_OK and access()
...
if( access ("/dev/null", F_OK ) != -1 ) {
printf("File already exists!\
");
} else {
printf("File doesn't exist!\
");
// create new dev here
} |
由于/dev/null确实存在,因此您会在此处看到"文件存在!"
- 当我尝试在模块中使用access时,gcc吐出:error: implicit declaration of function 'access'。我有#include <linux/unistd.h>,所以我不确定我缺少什么。
-
事实证明,从内核内部访问用户空间文件通常是一种不好的做法:kernelnewbies.org/FAQ/WhyWritingFilesFromKernelIsBad
-
@VilhelmGray-是的,对此感到抱歉,我正在考虑检查/ dev /是否存在的表单用户空间。在以下问题的可接受答案中查看链接:stackoverflow.com/questions/275386/…可以从内核访问文件系统,然后执行access()的操作,甚至尝试对open()进行特定操作/ dev检查它的存在...应该有更好的方法,但是我需要考虑一下
-
也许最佳实践是只在内核中注册设备,然后实施一个userland初始化脚本,该脚本将在执行mknod创建设备节点之前检查文件名是否存在冲突。但是话又说回来,这让我想知道为什么udev首先不会执行这种基本检查。
1
| This resulted in /dev/null being replaced by my character device file |
您可以使用mknod实用程序创建一个新的NULL设备文件
sudo mknod -m 0666 /dev/null c 1 3
设备节点的创建通常由用户空间操作处理。这是udev的目的:通过解释sysfm中的数据来填充和处理用户空间/dev/目录。
传递给device_create函数的名称只是一个建议的默认名称,它与有关该设备的其他数据一起出现在sysfm中。最终由用户空间实用程序或用户决定如何处理该数据。
udev遇到相同名称的设备时,默认行为是用新设备节点覆盖旧设备节点:http://marc.info/?l=linux-hotplug