Linux 传统上使用静态设备创建方法,因此大量设备节点在 /dev 下创建(有时上千个),而不管相应的硬件设备是否真正存在。通常这由一个MAKEDEV脚本实现,这个脚本包含了许多通过世界上(有幽默意味,注)每一个可能存在的设备相关的主设备号和次设备号对mknod程序的调用。采用udev的方法,只有被内核检测到的设备才会获取为它们创建的设备节点。因为这些设备节点在每次系统启动时被创建,他们会被贮存在ramfs(一个内存中的文件系统,不占用任何磁盘空间).设备节点不需要大量磁盘空间,因此它使用的内存可以忽略。
1:history
在2.4版本的kernel中,一种新文件系统称作devfs被添加了进去。尽管它在kernel源码中出现,然而这种动态创建设备的方法从未收到压倒性的支持from core kernel开发者;
devfs 的方法主要问题是 the way:设备检测,创建,命名。设备节点命名,可能是最critical的.It is generally accepted that 设备名允许是可配置的,then设备命名策略应该up to一个系统管理员,not 被欺骗by 特殊的开发者。devfs文件系统同时还忍受着一个紊乱情况,为它的design所固有,且不能被fix,若无实质的修改to kernel.现由于缺乏维护已被丢弃.
在2.6版本的kernel中,出现了一种叫sysfs的新虚拟文件系统。sysfs的 任务是export系统架构 to 用户空间进程。有了这种用户空间visible表示法,the possiblity of seeing a userspace replacement for devfs 变得更加现实。
2:udev 执行
sysfs怎样知道设备出现 在系统?应该使用什么设备号?对于被编进kernel的driver,当被kernel监测到时,直接注册目标with sysfs。使用模块方式编译的,当模块被load时,如前。once sysfs文件系统被mounted (on /sys),the data which the built-in drivers registered with sysfs are available to userspace process and to udev for device node creation.
udev初始化脚本创建这些 设备节点当linux boot时;这个脚本starts with 注册/sbin/udev/ 作为一个 hotplug事件管理者。热插拔事件不应该发生在这个过程中,然而udev is registered just in case they do occur.然后udevstart program walk through the /sys filesystem and 创建符合描述的设备在/dev。例如:/sys/class/tty/vcs/dev/包括string "7:0".这个字符串被udevstart使用来创建/dev/vcs,主设备号7and此设备号0。每一个udevstart创建的设备的权限设置来 自/etc/udev.d/permission.d/目录。这些numbered(有限的) 基本相似LFS bootscripts.如果找不到创建的设备权限文件,默认perissions to 600 and ownership to root:root./dev目录下创建的节点根据 /etc/udev/rules.d/目录下的文件来configured.
当一个新设备连 接被kernel监测到,kernel会产生一个hotplug event 并查找/proc/sys/kernel/hotplug去找出管理设备连接的用户空间程序。udev初始化脚本注册udev as this hander.当hotplug events发生时,kernel通知udev 去检测/sys 文件系统附属于这个新设备的信息并create 它的/dev/入口。
这带给我们一个问题:exists with udev,and likewise with devfs before it.?就像先有鸡还是先有蛋。大部分linux distrubtions
管 理加载模块通过/etc/modules.conf.access to 设备节点引起相应的kernel模块来加载。然而对于udev,这种方法不能正常工作,因为模块没有加载时,设备节点不存在。为了解决这个问题,模块脚本 加到了lfs-bootscripts包中,和/etc/sysconfig/modules在一起。通过添加module names到module file中,这些模块在计算机启动时被加载。这样,udev就可以去检测设备并创建相应的设备节点。
3:处理可热插拔/动态设备
当 你插入一个设备,比如usb mp3 player,内核辨认出设备连接同时产生一个热插拔事件。如果驱动已经loaded(不管是编进kernel还是通过s05modules bootscript加载),udev将被调用来创建相关的设备节点,根据sysfs data in /sys.如果刚插入的设备驱动以模块形式然而并未加载,那么刚attach to system 的设备只会引起kernel总线驱动产生一个热插拔事件通知用户空间一个新设备的连接and它不attached to a driver.结果,什么都没有发生,device依然不能使用。
如果建立一个system,that具有大量的以模块形式编译的驱动,使用s05modules并不实际。the hotplug package会显得非常有价值。当此包安装后,它会响应前述的kernel总线驱动hotplug事件。此包将加载相应的模块并为设备创建节点。
4:创建设备的问题
自动创建设备节点时常遇到的一些问题
1)A kernel driver may not exports its data to sysfs
当 使用第三方驱动(在kernel source tree 之外)时常遇到这种问题。
这些驱动end up时没有创建设备节点。使用/etc/sysconfig/creatfiles 配置文件to 人工创建设备。参考devices.txt文件(在kernel文档中)或者驱动文档来找出正确的major/minor设备号。
2)无硬件设备 is required.这种很常见with the advanced linux sound architecture(ALSA) project's open sound system(oss) compatibility 模块.这种形式的驱动可以使用以下下面两种方法来管理:
*将module names 加到 /etc/sysconfig/modules;
* 使用"install"line 在/etc/modprobe.conf中。This tells the modprobe command "when loading this module, also load this other module,at the same time."例如
install snd-pcm modprobe -i snd-pcm;modprobe snd-pcm-oss;true
当系统中有加载snd-pcm驱动的请求时,这会使系统加载both snd-pcm and snd-pcm-oss modules.
原文资料
Linux systems in general traditionally use a static device creation method, whereby a great many device nodes are created under /dev (sometimes literally thousands of nodes), regardless of whether the corresponding hardware devices actually exist. This is typically done via a MAKEDEV script, which contains a number of calls to the mknod program with the relevant major and minor device numbers for every possible device that might exist in the world. Using the udev method, only those devices which are detected by the kernel get device nodes created for them. Because these device nodes will be created each time the system boots, they will be stored on a ramfs (a file system that resides entirely in memory and does not take up any disk space). Device nodes do not require much disk space, so the memory that is used in negligable.
7.4.1. History
In February 2000, a new filesystem called devfs was merged into the 2.3.46 kernel and was made available during the 2.4 series of stable kernels. Although it was present in the kernel source itself, this method of creating devices dynamically never received overwhelming support from the core kernel developers.
The main problem with the approach adopted by devfs was the way it handled device detection, creation, and naming. The latter issue, that of device node naming, was perhaps the most critical. It is generally accepted that if device names are allowed to be configurable, then the device naming policy should be up to a system administrator, not imposed on them by any particular developer(s). The devfs file system also suffers from race conditions that are inherent in its design and cannot be fixed without a substantial revision to the kernel. It has also been marked as deprecated due to a lack of recent maintenance.
With the development of the unstable 2.5 kernel tree, later released as the 2.6 series of stable kernels, a new virtual filesystem called sysfs came to be. The job of sysfs is to export a view of the system's structure to userspace processes. With this userspace visible representation, the possibility of seeing a userspace replacement for devfs became much more realistic.
7.4.2. Udev Implementation
The sysfs filesystem was mentioned briefly above. One may wonder how sysfs knows about the devices present on a system and what device numbers should be used. Drivers that have been compiled into the kernel directly register their objects with sysfs as they are detected by the kernel. For drivers compiled as modules, this will happen when the module is loaded. Once the sysfs filesystem is mounted (on /sys), the data which the built-in drivers registered with sysfs are available to userspace processes and to udev for device node creation.
The S10udev initscript takes care of creating these device nodes when Linux is booted. This script starts with registering /sbin/udev as a hotplug event handler. Hotplug events (discussed below) should not be generated during this stage, but udev is registered just in case they do occur. The udevstart program then walks through the /sys filesystem and creates devices under /dev that match the descriptions. For example, /sys/class/tty/vcs/dev contains the string “7:0” This string is used by udevstart to create /dev/vcs with major number 7 and minor 0. The permissions of each and every device that udevstart creates are set using files from the /etc/udev.d/permissions.d/ directory. These are numbered in a similar fashion to the LFS bootscripts. If udev cannot find a permissions file for the device it is creating, it will default permissions to 600 and ownership to root:root. The names of the nodes created under the /dev directory are configured according to the rules specified in the files within the /etc/udev/rules.d/ directory.
Once the above stage is complete, all devices that were already present and have compiled-in drivers will be available for use. What about those devices that have modular drivers?
Earlier, we mentioned the concept of a “hotplug event handler.” When a new device connection is detected by the kernel, the kernel will generate a hotplug event and look at the file /proc/sys/kernel/hotplug to find out the userspace program that handles the device's connection. The udev initscript registered udev as this handler. When these hotplug events are generated, the kernel will tell udev to check the /sys filesystem for the information pertaining to this new device and create the /dev entry for it.
This brings us to one problem that exists with udev, and likewise with devfs before it. It is commonly referred to as the “chicken and egg” problem. Most Linux distrubtions handle
loading modules via entries in /etc/modules.conf. Access to a device node causes the appropriate kernel module to load. With udev, this method will not work because the device node does not exist until the module is loaded. To solve this, the S05modules bootscript was added to the lfs-bootscripts package, along with the /etc/sysconfig/modules file. By adding module names to the modules file, these modules will be loaded when the computer is starting up. This allows udev to detect the devices and create the appropriate device nodes.
Note that on slower machines or for drivers that create a lot of device nodes, the process of creating devices may take a few seconds to complete. This means that some device nodes may not be immediately accessible.
7.4.3. Handling Hotpluggable/Dynamic Devices
When you plug in a device, such a Universal Serial Bus (USB) MP3 player, the kernel recognizes that the device is now connected and generates a hotplug event. If the driver is already loaded (either because it was compiled into the kernel or because it was loaded via the S05modules bootscript), udev will be called upon to create the relevant device node(s) according to the sysfs data available in /sys. If the driver for the just plugged in device is available as a module but currently unloaded, then attaching the device to the system will only cause the kernel's bus driver to generate a hotplug event that notifies userspace of the new device connection and it not being attached to a driver. In effect, nothing happens and the device itself is not usable yet.
If building a system that has a lot of drivers compiled as modules rather than directly built into the kernel, using the S05modules may not be practical. The Hotplug package can be beneficial in these cases. When the Hotplug package is installed, it will respond to the aforementioned kernel's bus driver hotplug events. The Hotplug package will load the appropriate module and make this device available by creating the device node(s) for it.
7.4.4. Problems with Creating Devices
There are a few known problems when it comes to automatically creating devices nodes:
1) A kernel driver may not export its data to sysfs.
This is most common with third party drivers from outside the kernel tree. These drivers will not end up having their device nodes created. Use the /etc/sysconfig/createfiles configuration file to manually create the devices. Consult the devices.txt file inside the kernel documentation or the documentation for that driver to find the proper major/minor numbers.
2) A non-hardware device is required. This is most common with the Advanced Linux Sound Architecture (ALSA) project's Open Sound System (OSS) compatibility module. These types of devices can be handled in one of two ways:
*
Adding the module names to /etc/sysconfig/modules
*
Using an “install” line in /etc/modprobe.conf. This tells the modprobe command “when loading this module, also load this other module, at the same time.” For example:
install snd-pcm modprobe -i snd-pcm ; modprobe \
snd-pcm-oss ; true
This will cause the system to load both the snd-pcm and snd-pcm-oss modules when any request is made to load the driver snd-pcm.
相关问答 问: udev是什么? 它的目的何在?
答: 看看那篇 OLS 2003 上的有关 udev 的文章吧,可以在 docs 目录里找到,也能在这
里找到:OLS 2003 上还有一个关于 udev 的幻灯片。
问: udev 和 devfs 是什么关系
答: udev 完全在用户态 (userspace) 工作,利用设备加入或移除时内核所发送的
hotplug 事件 (event) 来工作。关于设备的详细信息是由内核输出 (export) 到位
于 /sys 的 sysfs 文件系统的。所有的设备命名策略、权限控制和事件处理都是在
用户态下完成的。与此相反,devfs 是作为内核的一部分工作的。
问: 如果 udev 不能完成所有 devfs 的工作的话,为什么把 devfs 标记为
OBSOLETE/removed?
答: 引用 Al Viro (Linux VFS 内核维护者):
- devfs 所做的工作被确信可以在用户态来完成。
- devfs 被加入内核之时,大家寄望它的质量可以迎头赶上。
- devfs 被发现了一些可修复和无法修复的 bug。
- 对于可修复的 bug,几个月前就已经被修复了,其维护者认为一切良好。
- 对于后者,同样是相当常一段时间以来没有改观了。
- devfs 的维护者和作者对它感到失望并且已经停止了对代码的维护工作。
问: 但是当一个并不存在的 /dev 节点被打开的时候,udev 并不能如 devfs 一样自动加
载驱动程序。
答: 的确如此,但 Linux 的设计是在设备被发现的时候加载模块,而不是当它被访问的时
候。
问: 不过等等,我确实希望 udev 可以在不存在的节点被打开的时候自动加载驱动。这是
我使用 devfs 的唯一原因了。给 udev 增加这个功能吧。
答: 不,udev 是用来管理 /dev 的,不是用来加载内核驱动的。
问: 嗨,求你们了。这不难做到的。
答: 这么个功能对于一个配置正确的计算机是多余的。系统中所有的设备都应该产生
hotplug 事件、加载恰当的驱动,而 udev 将会注意到这点并且为它创建对应的
设备节点。如果你不想让所有的设备驱动停留在内存之中,应该使用其它东西来
管理你的模块 (如脚本, modules.conf, 等等) 这不是 udev 的工作。
问: 但是我真的喜欢那个功能,还是加上吧
答: devfs 用的方法导致了大量无用的 modprobe 尝试,以此程序探测设备是否存在。
每个试探性探测都新建一个运行 modprobe 的进程,而几乎所有这些都是无用的。
问: 我喜欢 devfs 的设备文件命名方式,udev 可以这样命名么?
答: 可以,udev 可以使用 /dev 的命名策略来创建节点。通过一个配置文件,可以把内
核缺省的名字映射到 devfs 的名字。可以看看 udev 中带的 udev.rules.devfs 文
件。
注意: devfs 的命名方式是不被建议并且不被官方支持的,因为它所用的简单枚举设
备的方式在设备可能被随时加入或删除的情况下确实是一个比较笨的方法。这些编号
代给你的将只有麻烦,而并不能用来确定设备。看看那个永久性磁盘 (persistent
disk) 的规则就知道如何在用户态下正确的做这件事,而不是傻傻地列出设备。
问: udev 可以为哪些设备创建节点?
答: 所有在 sysfs 中显示的设备都可以由 udev 来创建节点。如果内核中增加了其它设
备的支持,udev 也就自动地可以为它们工作了。现在所有的块设备都在被支持之列,
大部分的主字符设备也是被支持的。内核开发者们正致力于让所有的字符设备都被支
持。可以到 linux-kernel 邮件列表上寻找补丁或是查看补丁的状态。
问: udev 是否会去掉匿名设备数量的限制?
答: udev 完全工作于用户态。如果内核支持了更多的匿名设备,udev 就会支持。
问: udev 是否会支持符号链接?
答: udev 现在就支持符号链接,每个设备节点拥有多个符号链接也是被支持的。
问: udev 如何处理 /dev 文件系统?
答: 建议使用一个每次启动系统的时候重新创建的 tmpfs 作为 /dev 的文件系统。不过
实际上 udev 并不关心那种文件系统在被使用。
问: 在 init 运行之前,udev 如何处理设备?
答: udev 可以被放入 initramfs 之中,并在每个设备被发现的时候运行。也可以让
udev 工作在一个真的根分区被加载之后根据 /sys 的内容创建的初始 /dev 目录
之中。
问: 我是否可以利用 udev 在一个 USB 设备被加载的时候自动加载上这个设备?
答: 技术上讲是可以的,但是 udev 不是用于这个工作的。所有的主流发布版 (distro)
都包含了 HAL 用于这个工作,它
也是专门用于监视设备变更的,并且集成进入了桌面软件。
换个角度说,这可以简单的通过 fstab 来实现:
/dev/disk/by-label/PENDRIVE /media/PENDRIVE vfat user,noauto 0 0
这样,用户可以用如下命令来访问设备:
$mount /media/PENDRIVE
同样不需要管理员权限,但却拥有了设备的全部访问权限。使用永久性磁盘链接
(label, uuid) 将可以指定同一设备,无论其实际上的内核名字是什么。
问: 有什么我需要注意的安全问题么?
答: 当使用动态设备编号的时候,一个给定的主/从设备号可能在不同时间对应不同的设
备,如果一个用户拥有对这个节点的访问权限,并且可以创建一个到这个节点的硬链
接,他就可以如此得到一个这个设备节点的拷贝。当设备被移除之后,udev 删除了
设备节点,但硬链接依然存在。如果这个设备节点之后被重新使用不同的访问权限被
创建的时候,其硬链接仍然可以使用先前的访问权限来访问。
(同样的问题也存在在使用 PAM 改变访问权限的 login 上。)
简单的解决方案就是通过把 /dev 放在 tmpfs 这样的单独的文件系统之上来防止建
立硬链接。