Ubuntu设备管理udev
参考资料:
@Ubuntu manuals udev
@CLEARPATH UDEV RULES
udev: Linux dynamic device management
udev的主要作用是完成设备的动态管理
udev提供了与硬件外设之间的系统软件, 负责管理各设备的权限以及将设备通过
symlink
挂载到/dev/
目录下, 为设备赋予别名.
通常情况下, linux的内核会基于发现顺序(先插进去不一定会优先读取)随机为连接的设备分配一个设备名(device name), 因此如果想要可靠的调用某一个设备, 就需要为该设备配置一个规则, 根据别名来进行设备的调用.
symlink
的作用就是根据设备的属性(properties)或者当前的配置为设备取别名, 之后可以通过symlink
来唯一标识该设备
udev 守护进程(udev daemon)
该守护进程通过systemd-udevd.service
配置, 直接从内核中读取设备的添加与移除或者状态的改变. 当udev被硬件设备的事件(uevent)触发, 会根据之前配置好的规则(通常位于/etc/udev/rules.d/*
)与设备的各种属性进行匹配, 根据这些属性来识别设备.
属性包括: 设备类型 制造商ID(idVendor), 产品ID(idProduct), 序列号(serial)等
udev rules
udev规则文件可以位于不同的目录中,通常是/etc/udev/rules.d/
一般用来存放用户自定义的规则, 和/lib/udev/rules.d/
这里存放的是系统默认的以及包管理器管理的规则. 所有的规则文件, 必须 以.rules
结尾, 其他的后缀名会被忽略
所有的udev规则文件中, 每一行至少需要包含一组键值对, 空行与注释行(以#
开头)除外.
键值对分为两类, 匹配型(match)以及配置型(assignment), 如果匹配型键值对完全吻合, 则后面的配置型键值对会对该设备进行配置, 应用用户定义的规则
在udev规则中,键值对用于匹配设备属性或指定规则应该执行的动作。每个键(key)后面可以跟随一个操作符(operator),用来定义键和值之间的关系或者操作的类型。不同的操作符有不同的含义,根据操作符的不同,规则可以用来匹配设备、设置属性或执行某些操作。以下是一些有效的操作符及其含义:
==
(比较操作符)
- 用于匹配。如果设备的属性与指定的值相等,则匹配成功。
- 例如:
ATTRS{idVendor}=="0483"
匹配制造商ID为0483的设备。
!=
(不等操作符)
- 用于匹配。如果设备的属性与指定的值不相等,则匹配成功。
- 例如:
ATTRS{idVendor}!="0483"
匹配所有制造商ID不是0483的设备。
=
(赋值操作符)
- 用于设置属性值。
- 例如:
NAME="my_device"
将匹配的设备的名称设置为my_device
。
+=
(追加操作符)
- 用于向属性追加一个值,或者向列表中添加一个元素。
- 例如:
ENV{ID_USB_DRIVER}+="my_driver"
将my_driver
添加到ID_USB_DRIVER
环境变量中。
-=
(移除操作符)
- 用于从列表中移除一个元素。
- 此操作符较少使用,且应用场景受限。
:=
(赋值一次操作符)
- 用于永久设置属性值。一旦设置,其他规则不能更改此属性。
- 例如:
NAME:="fixed_name"
将设备名称永久设置为fixed_name
,之后的规则无法更改。
?=
(条件赋值操作符)
- 仅当变量未被设置时,才对其赋值。
- 例如:
ENV{ID_FS_TYPE}?="unknown"
如果ID_FS_TYPE
环境变量未设置,则将其设置为unknown
。
udev规则文件的排序规则为字典顺序(lexical order), 即数字小的优先执行, 数字执行完以后执行字母开头的规则, 后执行的会覆盖掉前面的规则
下面是一个编写rules的例子
shell
# /etc/udev/rules.d/99-usb-serial.rules
# 规则1: 对于特定制造商ID和产品ID的USB设备,设置SYMLINK和权限
SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE="0666", SYMLINK+="my_usb_device"
# 规则2: 对于具有特定序列号的设备,执行一个脚本
SUBSYSTEM=="usb", ATTRS{serial}=="123456789", RUN+="/path/to/your/script.sh"
# 规则3: 对于特定制造商ID和产品ID的tty设备,改变所有者和组
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", OWNER="username", GROUP="dialout", MODE="0660"
# 注意:
# - SUBSYSTEM 指明了设备的子系统。
# - ATTRS{idVendor} 和 ATTRS{idProduct} 分别指定了USB设备的制造商ID和产品ID。
# - ATTRS{serial} 指定了设备的序列号。
# - MODE 设置了设备文件的权限(例如,0666 表示所有用户都可以读写设备)。
# - SYMLINK+= 为设备创建了一个符号链接,使其更容易被访问。
# - RUN+= 指定了当规则匹配时要执行的命令或脚本。
# - OWNER 和 GROUP 分别指定了设备文件的所有者和所属组。
当新建了一个rules之后, 需要重新加载udev规则
shell
sudo udevadm control --reload-rules
sudo udevadm trigger
附录1: 匹配规则键及其作用
键名 | 描述 |
---|---|
ACTION |
匹配事件动作的名称。 |
DEVPATH |
匹配事件设备的devpath。 |
KERNEL |
匹配事件设备的名称。 |
NAME |
用于网络接口的名称。一旦在前面的规则中设置了NAME 键,就可以使用它。网络设备节点的名称不能通过udev更改,只能创建额外的符号链接。 |
SYMLINK |
匹配指向节点的符号链接的名称。一旦在前面的规则中设置了SYMLINK 键,就可以使用它。每个匹配的规则都将此值添加到要创建的符号链接列表中。 |
SUBSYSTEM |
匹配事件设备的子系统。 |
DRIVER |
匹配事件设备的驱动程序名称。仅在事件生成时设备已绑定到驱动程序的情况下设置此键。 |
ATTR{filename} |
匹配事件设备的sysfs属性值。尾随空格在属性值中被忽略,除非指定的匹配值本身包含尾随空格。 |
KERNELS |
向上搜索devpath以匹配设备名称。 |
SUBSYSTEMS |
向上搜索devpath以匹配设备子系统名称。 |
DRIVERS |
向上搜索devpath以匹配设备驱动程序名称。 |
ATTRS{filename} |
向上搜索devpath以匹配具有相应sysfs属性值的设备。如果指定了多个ATTRS 匹配项,则所有这些项必须在同一个设备上匹配。尾随空格的处理同ATTR{filename} 。 |
TAGS |
向上搜索devpath以匹配具有相应标签的设备。 |
ENV{key} |
匹配设备属性值。 |
TAG |
匹配设备标签。 |
TEST{octal mode mask} |
测试文件的存在。如果需要,可以指定一个八进制模式掩码。 |
PROGRAM |
执行一个程序以确定是否匹配;如果程序成功返回,则此键为真。设备属性在执行的程序环境中可用。程序的stdout在RESULT 键中可用。仅适用于非常短暂的前台任务。详见RUN 。 |
RESULT |
匹配最后一次PROGRAM 调用返回的字符串。这个键可以在相同的或任何后续规则中使用。 |
附录2: 配置规则键及其作用
键 | 说明 |
---|---|
NAME | 用于网络接口的名称。设备节点的名称不能通过udev改变,只能创建额外的符号链接。 |
SYMLINK | 指向节点的符号链接的名称。每个匹配规则都会将此值添加到要创建的符号链接列表中。允许的命名字符包括[0-9A-Za-z#+-.:=@_/] 、有效的utf8字符序列和"\x00"十六进制编码,所有其他字符都被替换为'_'。可以通过用空格分隔名称来指定多个符号链接。符号链接名称绝不能与内核的默认设备节点名称冲突,以避免不可预测的行为。 |
OWNER, GROUP, MODE | 设备节点的权限。指定的值会覆盖默认值。 |
ATTR{key} | 将指定的值写入事件设备的sysfs属性。 |
ENV{key} | 设置设备属性值。以'.'开头的属性名称既不存储在数据库中,也不导出给事件或外部工具。 |
TAG | 为设备附加一个标签。这用于过滤事件,供libudev的监视功能使用,或用于枚举一组标签设备。仅意味在具有特定设备过滤要求的上下文中使用,并不作为通用标志。过度使用可能导致事件处理效率低下。 |
RUN{type} | 在处理特定事件的所有规则后,添加一个要执行的程序列表,取决于类型:program (执行指定的外部程序)或builtin (使用内置程序而非外部程序)。此项仅适用于非常短暂的前台任务。对于udev事件,启动守护进程或其他长时间运行的进程是不合适的;分叉的进程,无论是否分离,都会在事件处理完成后无条件被杀死。 |
LABEL | 一个命名的标签,GOTO可跳转至此。 |
GOTO | 跳转到下一个匹配的LABEL。 |
IMPORT{type} | 根据类型从不同来源导入一组变量作为设备属性,包括外部程序(program )、内置程序(builtin )、文本文件(file )、当前设备数据库(db )、内核命令行(cmdline )或父设备属性(parent )。 |
WAIT_FOR | 等待文件变得可用,或直到10秒的超时过期。路径相对于sysfs设备;如果未指定路径,则等待属性出现。 |
OPTIONS | 设置规则和设备选项,如link_priority (创建符号链接的优先级)、event_timeout (事件等待操作完成的秒数)、string_escape (字符串转义模式)、static_node (静态设备节点权限)、watch (使用inotify监视设备节点)和nowatch (禁用inotify监视)。 |
替换 | 支持使用$kernel , $number , $devpath , $id , $driver , $attr{file} , $env{key} , $major , $minor , $result , $parent , $name , $links , $root , $sys , $devnode , %% , 和 $$ 等替换符,用于NAME, SYMLINK, PROGRAM, OWNER, GROUP, MODE和RUN字段中。替换允许基于设备属性、环境变量等动态值。 |