udev的设计目标:
- 在用户空间中执行
- 动态建立/删除设备文件
- 允许每个人都不用关心主/次设备号
- 提供LSB标准名称
- 如果需要,可以提供固定的名称。
使用udev后,在/dev目录下就只包含系统中真正存在的设备。为了提供这些功能,udev以3个分割的子计划发展:namedev、libsysfs和udev。namedev为设备命名子系统,libsysfs提供访问sysfs文件系统从中获取信息的标准接口,udev提供/dev设备节点文件的动态创建和删除策略。udev程序承担与namedev和libsysfs库交互的任务,当/sbin/hotplug程序被内核调用时,udev被运行。udev的工作过程如下:
(1)当内核检测到在系统中出现了新设备后,内核会在sysfs文件系统中为该新设备生成新的记录并导出一些设备特定的信息所发生的事件。
(2)udev获取内核导出的信息,它调用namedev决定应给该设备置顶的名称,如果时新插入的设备,udev将调用libsysfs决定应该为该设备的设备的设备文件置顶的主/次设备号,并用分析获得的设备名称和主/次设备号创建/dev中的设备文件,如果是设备移除,则之前已经被创建的/dev文件将被删除。
udev只支持linux-2.6内核,因为udev严重依赖于sysfs文件系统提供的信息。它的配置文件是/etc/udev/udev.conf,该文件一般缺省有这样几项:
udev_root="/dev" ; udev产生的设备文件的根目录是/dev
udev_db="/dev/.udevdb" ; 通过udev产生的设备文件形成的数据库
udev_rules="/etc/udev/rules.d" ;用于指导udev工作的规则所在目录。
udev_log="err" ;当出现错误时,用syslog记录错误信息。
udev的规则文件以行为单位,以"#"开头的行代表注释行。其余的每一行代表一个规则。每个 规则分成一个或多个“匹配”和“赋值”部分。“匹配”部分用“匹配“专用的关键字来表示,相应的“赋值”部分用“赋值”专用的关键字来表示。“匹配”关键 字包括:ACTION,KERNEL,BUS, SYSFS等等,“赋值”关键字包括:NAME,SYMLINK,OWNER等等。例如:
SUBSYSTEM=="net", ACTION=="add", SYSFS{address}=="00:0d:87:f6:59:f3", IMPORT="/sbin/rename_netiface %k eth0"
这个规则中的“匹配”部分有三项,分别是SUBSYSTEM,ACTION和SYSFS。而"赋值"部分有一项,是IMPORT。这个规则就是说,当系统 中出现的新硬件属于net子系统范畴,系统对该硬件采取的动作是加入这个硬件,且这个硬件在SYSFS文件系统中的“address”信息等于“00: 0d..."时,对这个硬件在udev层次施行的动作是调用外部程序/sbin/rename_netiface,传递的参数有两个,一个是“%k”,代 表内核对该新设备定义的名称。另一个是”eth0“。
从上面这个例子中可以看出,udev的规则的写法比较灵活的,尤其在“匹配”部分中,可以通过诸如”*“, ”?“,[a-c],[1-9]等shell通配符来灵活匹配多个匹配项。具体的语法可以参考udev的man文档。
udev是通过对内核产生的设备名增加别名的方式来达到上述目的的。前面说过,udev是用户模式程序,不会更改内核的行为。因此,内核依然会我 行我素地产生设备名如sda,sdb等。但是,udev可以根据设备的其他信息如总线(bus),生产商(vendor)等不同来区分不同的设备,并产生 设备文件。udev只要为这个设备文件取一个固定的文件名就可以解决这个问题。在后续对设备的操作中,只要引用新的设备名就可以了。但为了保证最大限度的 兼容,一般来说,新设备名总是作为一个对内核自动产生的设备名的符号链接(link)来使用的。
例如:内核产生了sda设备名,而根据信息,这个设备对应于是我的内置硬盘,那我就可以制定udev规则,让udev除了产生/dev/sda设备文件 外,另外创建一个符号链接叫/dev/internalHD。这样,我在fstab文件中,就可以用/dev/internalHD来代替原来的 /dev/sda了。下次,由于某些原因,这个硬盘在内核中变成了sdb设备名了,那也不用着急,udev还会自动产生/dev/internalHD这 个链接,并指向正确的/dev/sdb设备。所有其他的文件像fstab等都不用修改。