Udev (用户设备目录/dev)是 Linux 系统用于动态设备管理的子系统。自系统内核 2.6 以后,Udev 取代了之前的 devfs 和 hotplug 来进行设备文件维护和热插拔。
Udev 会在设备启动时来侦测是否添加或移除了某些设备,并动态在系统中创建或删除设备节点(即设备驱动程序的接口,该接口显示在文件系统中,好像它是一个普通文件,存储在/dev目录下)。之后,它会将有关设备的信息或其状态的更改回传到用户空间。
它的主要功能包括:1)向系统应用程序提供设备事件;2)管理设备节点的权限;3)可以在/dev目录中创建用于访问设备的有用符号链接,甚至重命名网络接口。
Udev的优点之一是,它可以使用持久的设备名称来保证在重新启动时设备的一致命名,而不管它们的发现顺序如何。此功能很有用,因为内核只是根据发现顺序分配不可预测的设备名称。
在本文中,我们将演示如何在 Linux 系统上使用 Udev 进行设备检测和管理。需要指出的是,大多数(如果不是所有)主流现代 Linux 发行版都附带 Udev 作为默认安装的一部分。
Linux Udev 基础知识
udev 守护进程 systemd-udevd(或者是 systemd-udevd.service),每当系统有添加或删除设备或设备更改其状态事件时,都会与内核通信并直接从内核接收该设备事件。
Udev 是基于规则来进行工作的,这些规则不仅灵活而且功能强大。每个设备事件都会匹配 /lib/udev/rules.d 和 /run/udev/rules.d 目录定义的规则。
我们可以尝试在 /etc/udev/rules.d/ 创建规则文件(.rules 扩展名的文件)来处理一个设备,注意,这个目录的规则文件需要具有最高权限。
为了创建设备节点文件,udev 需要使用某些属性来标识设备,如标签、序列号、使用的主要和次要编号、总线设备编号等。此信息由 sysfs 文件系统导出。
无论何时将设备连接到系统,内核都会检测并初始化它,并在 /sys/directory 下创建一个具有设备名称的目录,该目录存储设备属性。
udev 的主要配置文件是 /etc/udev/udev.conf,为了控制 udev 守护进程的运行时行为,可以使用 udevadm 实用程序来管理它。
要显示接收到的内核事件(UEVENT)和 udev 事件(udev 在规则处理后发送),可以使用 monitor 参数执行 udevadm。然后将设备连接到系统,就会从终端显示设备事件是如何处理的。
以下屏幕截图显示了将 U 盘连接到系统后设备内核事件的摘录:
图.1 udevadm monitor监测 U 盘事件
为了查看设备信息,可以使用”lsblk”命令来显示相关内容:
# lsblk
图.2 lsblk 显示块文件信息
从输出可以看出,U 盘设备被命名为 sdb1 和 sdb2(绝对路径是/dev/sdb1 和 /dev/sdb2),可以通过 udevadm info 命令来查看设备的相关信息:
# udevadm info /dev/sdb1
图.3 udevadm info 查看设备属性信息
Linux Udev 规则如何工作
本节,我们将简要讨论如何编写 udev 规则。规则由一个或多个键值对的逗号分隔列表组成。规则允许从默认名称重命名设备节点,修改设备节点的权限和所有权。规则会在创建或删除设备节点时触发程序或脚本的执行。
我们将编写一个简单的规则,用于在添加USB设备和从运行系统中删除USB设备时触发脚本。
我们首先创建两个脚本,用于在规则中执行:
# vim /bin/device_added.sh # vim /bin/device_removed.sh
内容分别如下:
device_added.sh: #!/bin/bash echo "USB device added at $(date)" >>/tmp/scripts.log device_removed.sh: #!/bin/bash echo "USB device removed at $(date)" >>/tmp/scripts.log
之后,给两个脚本添加可执行权限:
# chmod +x /bin/device_added.sh # chmod +x /bin/device_removed.sh
之后,创建规则文件”/etc/udev/rules.d/80-test.rules”来触发以上两个脚本。规则文件内容如下:
SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="/bin/device_added.sh" SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="/bin/device_removed.sh"
规则文件中:
- == 表示相等
- += 表示添加
- SUBSYSTEM 表示匹配的设备
- ACTION 表示匹配的设备事件
- ENV{DEVTYPE} 表示匹配的设备属性值,示例使用的是设备类型值
- RUN 表示匹配事件后执行的脚本或命令
保存所有文件后,重新启动 udevd 进行以使自定义的规则生效,命令如下:
# udevadm control --reload
最后,就可以插拔 U 盘来看自定义规则是否被正确执行了。如果脚本被正确执行,在 U 盘的插拔事件后,都会在 /tmp/scripts.log 文件中产生相应的内容,查看该文件内容即可验证自定义规则是否生效了:
# ls -l /tmp/scripts.log # cat /tmp/scripts.log
图.4 自定义 udev 规则
有关如何编写 udev 规则和管理 udev 的更多信息,可以通过以下命令分别查阅 udev 和 udevadm 手册信息:
# man udev # man duevadm