使用 udev 高效、动态地管理 Linux 设备文件

udev 是 Linux 内核的设备管理器。总的来说,它取代了 devfs 和 hotplug,负责管理 /dev 中的设备节点。同时,udev 也处理所有用户空间发生的硬件添加、删除事件,以及某些特定设备所需的固件加载。

Linux 用户常常会很难鉴别同一类型的设备名,比如 eth0, eth1, sda, sdb 等等。通过观察这些设备的内核设备名称,用户通常能知道这些是什么类型的设备,但是不知道哪一个设备是他们想要的。例如,在一个充斥着本地磁盘和光纤磁盘的设备名清单 (/dev/sd) 中,用户无法找到一个序列号为“35000c5008c194e6a”的磁盘。在这种情况下,udev 就能动态地在 /dev目录里产生自己想要的、标识性强的设备文件或者设备链接,以此帮助用户方便快捷地找到所需的设备文件。
2012年4月,udev被合并至systemd。

系统架构
udev系统可以分为三个部分:

libudev函数库,可以用来获取设备的信息。
udevd守护进程,处于用户空间,用于管理虚拟/dev
管理命令udevadm,用来诊断出错情况。

下面的流程图显示 udev 添加 / 删除设备文件的过程。

image001

命名格式

BUS 总线 KERNEL 内核名如sd ID 设备id 如总线id PLACE
SYSFS{filename} 或 ATTR{filename}
PROGRAM 调用外部程序 RESULT 匹配program返回的结果 NAME
SYMLINK 连接规则*

编写规则

udev配置文件是/etc/udev/udev.conf,文件内容中很重要的一项是指定udev规则存储的目录,形如udev_rules=“/etc/udev/rules.d”. 指定的目录中存储一系列以.rules结束的规则文件,每个文件处理一系列规则来帮助udev分配名字给设备文件并保证内核可以识别此名字。

规则文件由系列键-值对组成,键值对分两类:匹配键(使用操作符”==”,”!=”等)和赋值键(使用”=”,”+=”,”:=”等)。匹配键判断规则是否应被应用,赋值键可以被分配一到多个值。

有些常用的键已经有了固定的含义,这里列举出最基本的几个。这也是基本规则之一,更多编辑规则请参见man udev页。

KERNEL – 匹配设备的内核名字
SUBSYSTEM – 匹配设备的子系统
DRIVER – 匹配设备驱动名
NAME – 应当被采用为设备节点的名字
SYMLINK – 一系列被作为设备节点替补名字的符号链接
常用键举例:KERNEL==”hdb”, DRIVER==”ide-disk”, NAME=”my_spare_disk”, SYMLINK+=”sparedisk”

udev 的简单规则:
可以参考arch wiki
https://wiki.archlinux.org/index.php/Udev_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

制定 udev 规则和查询设备信息的实例:

如何查找设备的信息 ( 属性 ) 来制定 udev 规则:

当我们为指定的设备设定规则时,首先需要知道该设备的属性,比如设备的序列号、磁盘大小、厂商 ID、设备路径等等。通常我们可以通过以下的方法获得:

查询sysfs文件系统:
前面介绍过,sysfs 里包含了很多设备和驱动的信息。

例如:设备 sda 的 SYSFS{size} 可以通过 cat /sys/block/sda/size得到;SYSFS{model} 信息可以通过 cat /sys/block/sda/device/model得到。

        zs@zs-PC:~$ cat /sys/block/sda/device/model 
               ST1000DM003-1ER1

udevadm命令:
udevadm 可以查询 udev 数据库里的设备信息。例如:用 udevadm 查询设备 sda 的 model 和 size 信息:

通过 udevadm 查询设备属性的例子

        zs@zs-PC:~$ sudo udevadm info -a  /dev/sda | grep model
            ATTRS{model}=="ST1000DM003-1ER1"

其他外部命令:

通过 scsi_id 查询磁盘的 SCSI_ID 的例子

    zs@zs-PC:~$ sudo /lib/udev/scsi_id -g /dev/sda
          35000c5008c194e6a

udevadm test会针对一个设备,在不需要 uevent 触发的情况下模拟一次 udev的运行,并输出查询规则文件的过程、所执行的行为、规则文件的执行结果。通常使用 udevadm test来调试规则文件。以下是一个针对设备 sda 的 udevadm test例子。由于 udevadm test是扫描所有的规则文件 ( 包括系统自带的规则文件 ),所以会产生冗长的输出。为了让读者清楚地了解 udevtest,以开发一次错误规则为例:

    zs@zs-PC:~$ cat /lib/udev/rules.d/99-removable-ext-filesystem-add-noexec-mount-option.rules 
#Skip this section below if this device is not connected by USB
ACTION!="add|change", GOTO="exit"
BUS!="usb", GOTO="exit"
SUBSYSTEM!="block", GOTO="exit"
SYSFS{removable}!="1" GOTO="exit"
ENV{ID_FS_TYPE}!="ext[234]" GOTO="exit"
#Set mount options of UDisks2(pathched on Deepin)
ENV{UDISKS_MOUNT_OPTIONS}="noexec"

udevadm test 的执行过程

    zs@zs-PC:~$ sudo udevadm test /dev/sda
calling: test
version 239
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.
Load module index
Parsed configuration file /lib/systemd/network/99-default.link
Created link configuration context.
Reading rules file: /lib/udev/rules.d/01-md-raid-creating.rules
Reading rules file: /lib/udev/rules.d/39-usbmuxd.rules
....
Reading rules file: /lib/udev/rules.d/99-laptop-mode.rules
Reading rules file: /lib/udev/rules.d/99-removable-ext-filesystem-add-noexec-mount-option.rules
Invalid rule /lib/udev/rules.d/99-removable-ext-filesystem-add-noexec-mount-option.rules:3: unknown key 'BUS'
Invalid rule /lib/udev/rules.d/99-removable-ext-filesystem-add-noexec-mount-option.rules:5: unknown key 'SYSFS{removable}'
Reading rules file: /lib/udev/rules.d/99-systemd.rules
Reading rules file: /lib/udev/rules.d/99-vmware-scsi-udev.rules
Reading rules file: /etc/udev/rules.d/dhhvux-load.rules
Reading rules file: /lib/udev/rules.d/ukeys.rules
rules contain 393216 bytes tokens (32768 * 12 bytes), 42284 bytes strings
32070 strings (261869 bytes), 27924 de-duplicated (223732 bytes), 4147 trie nodes used
unable to open device '/sys/dev/sda'
Unload module index
Unloaded link configuration context

可以看出:

    Invalid rule /lib/udev/rules.d/99-removable-ext-filesystem-add-noexec-mount-option.rules:3: unknown key 'BUS'
 Invalid rule /lib/udev/rules.d/99-removable-ext-filesystem-add-noexec-mount-option.rules:5: unknown key 'SYSFS{removable}'

这个开发在15.9里面对usb设备noexec 规则,可以看到部分规则编写不对。部分key失效,规则对所有设备生效了。

正确规则后来改为:

    zs@zs-PC:~$ cat /lib/udev/rules.d/99-removable-ext-filesystem-add-noexec-mount-option.rules 
#Skip this section below if this device is not connected by USB
#Set mount options of UDisks2(pathched on Deepin)
ACTION!="add|change",ENV{ID_BUS}=="usb", ENV{ID_USB_DRIVER}=="usb-storage", SUBSYSTEM=="block",
    ENV{ID_FS_TYPE}=="ext[234]", ENV{UDISKS_MOUNT_OPTIONS}="noexec"

不写了,我要赶紧推这个修复更新去了….

1 条思考于 “使用 udev 高效、动态地管理 Linux 设备文件

发表评论

电子邮件地址不会被公开。 必填项已用*标注