`misc_register()` 不检查 `/dev/` 中是否存在该名称。

huangapple go评论71阅读模式
英文:

misc_register() does not check if name exists in /dev/

问题

我是新手,对Linux内核和设备不太熟悉,我尝试了以下实验:

  • 创建一个名为"mydev"的设备节点:

sudo mknod /dev/mydev c 100 101

  • 插入一个杂项模块,尝试注册一个名为"mydev"的设备:
// misc_hello.c
static struct miscdevice helloworld_miscdevice = {
   	.minor = MISC_DYNAMIC_MINOR,
   	.name = "mydev",
   	.fops = &my_dev_fops,
};

static int __init hello_init(void)
{
   int ret_val;
   ret_val = misc_register(&helloworld_miscdevice);
   // ret_val为0,所以设备已成功注册

执行insmod misc_hello.ko后,我在dmesg中看不到任何错误。当我使用ls /dev/ | grep mydev检查设备时,我看到dev/mydev/节点是之前用mknod命令手动创建的节点。如果sysfs发现有另一个同名设备节点,模块注册不应该失败吗?Linux内核如何检测节点之间的名称冲突?

英文:

I am newbie with Linux kernel/devices and I have tried the following experiment:

  • Create a node with device name "mydev":

sudo mknod /dev/mydev c 100 101

  • Insert a misc module which tries to register a device with name "mydev":
// misc_hello.c
static struct miscdevice helloworld_miscdevice = {
   	.minor = MISC_DYNAMIC_MINOR,
   	.name = "mydev",
   	.fops = &my_dev_fops,
};

static int __init hello_init(void)
{
   int ret_val;
   ret_val = misc_register(&helloworld_miscdevice);
   // ret_val is 0 so the device is registered succesfully

After executing insmod misc_hello.ko, I don't see any error in dmesg. When I inspect the devices with ls /dev/ | grep mydev I see that the dev/mydev/ node is the one created manually before with mknode command. Shouldn't the module registration fail if sysfs finds that there is another device node with the same name? How is name conflict between nodes detected by Linux kernel?

答案1

得分: 1

策略规定,即使动态填充,用户空间对/dev的内容负有最终责任。

如果支持devtmpfs文件系统(从内核版本2.6.32起由CONFIG_DEVTMPFS选项支持),内核将尝试填充它,但不关心是否无法创建设备节点,就像不关心devtmpfs文件系统是否已挂载一样。一旦挂载,用户空间(例如udevd)随时可以修改devtmpfs文件系统的内容。正如原始提交中所述:

Devtmpfs可以随时由用户空间更改和修改,以任何所需的方式 - 就像今天的udev-mounted tmpfs一样。未经修改的udev版本将在其上正常运行,并识别已经存在的内核创建的设备节点并使用它。默认节点权限为root:root 0600。仍然需要由用户空间应用适当的权限和用户/组所有权、有意义的符号链接以及所有其他策略。

如果由devtmps创建了节点,当设备消失时,devtmpfs将删除设备节点。如果设备节点是由用户空间创建的,或者由用户空间替换了devtmpfs创建的节点,那么它将不再被devtmpfs删除。

如果将/dev挂载为tmpfs而不是devtmpfs,内核根本不会填充它,但仍然可以由用户空间填充(例如udevd)。

内核通过从device_add()函数调用devtmpfs_create_node(dev);来自动创建设备节点,并通过从device_del()函数调用devtmpfs_delete_node(dev);来自动删除设备节点。虽然devtmpfs_create_node()devtmpfs_delete_node()函数在出错时返回负错误号,但这些函数的调用返回值会被device_add()device_del()函数忽略。

英文:

Policy dictates that userspace has ultimate responsibility for the contents of /dev, even when populated dynamically.

If the devtmpfs file system is supported (by the CONFIG_DEVTMPFS option since kernel version 2.6.32), the kernel will attempt to populate it, but it does not care if it fails to create a device node, just as it does not care if the devtmpfs file system is mounted or not. When mounted, the contents of the devtmpfs file system can be modified by userspace (e.g. by udevd) at any time. As it says in the original commit:

> Devtmpfs can be changed and altered by userspace at any time, and in any way needed - just like today's udev-mounted tmpfs. Unmodified udev versions will run just fine on top of it, and will recognize an already existing kernel-created device node and use it. The default node permissions are root:root 0600. Proper permissions and user/group ownership, meaningful symlinks, all other policy still needs to be applied by userspace.
>
> If a node is created by devtmps, devtmpfs will remove the device node when the device goes away. If the device node was created by userspace, or the devtmpfs created node was replaced by userspace, it will no longer be removed by devtmpfs.

If /dev is mounted as a tmpfs rather than a devtmpfs, the kernel does not populate it at all, but it can still be populated by userspace (e.g. by udevd).

The automatic creation of the device node by the kernel is done by the call to devtmpfs_create_node(dev); from the device_add() function, and the automatic deletion is done by the call to devtmpfs_delete_node(dev); from the device_del() function. Although the devtmpfs_create_node() and devtmpfs_delete_node() functions to return a negative error number on error, the return values of calls to those functions are ignored by the device_add() and device_del() functions.

huangapple
  • 本文由 发表于 2023年5月11日 16:03:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76225361.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定