udev 规则(udev Rule)是 Linux 用户态设备管理器 udev 使用的匹配和动作配置,用来根据内核设备事件与 sysfs 属性,为设备节点设置权限、所属组、稳定软链接、环境变量或触发脚本。
在 USB 场景中,它常用 VID:PID、序列号、接口号或 USB 物理路径,把“某类刚插入的设备”变成“普通用户可以访问、路径稳定、脚本能识别的设备”。
核心问题
Linux 内核发现设备后,会通过设备模型和 sysfs 暴露属性,并发出 hotplug 事件。问题是:
- 默认设备节点权限可能只允许 root 访问。
/dev/ttyUSB0、/dev/video2这类编号会随插拔顺序变化。- 同型号多设备需要稳定区分。
- 有些设备插入后需要加载权限、创建别名或触发初始化动作。
udev 规则解决的是“根据设备属性把内核发现的设备映射成用户态可管理资源”的问题。
核心对象
| 对象 | 含义 | 工程关注点 |
|---|---|---|
| kernel uevent | 内核设备事件 | add、remove、change 等动作 |
| sysfs attribute | /sys 下的设备属性 | idVendor、idProduct、serial、interface 等 |
| match key | 规则左侧匹配条件 | SUBSYSTEM、ATTR{}、KERNEL、ENV{} |
| assignment key | 规则右侧动作 | MODE、GROUP、SYMLINK、TAG、RUN |
| device node | /dev 下的节点 | 权限和命名常由 udev 处理 |
| rule file | /etc/udev/rules.d/*.rules 等文件 | 数字前缀影响规则顺序 |
核心机制
1. 事件进入 udev
设备在 USB 枚举 或其他总线发现后,内核发出 uevent。udevd 收到事件后,会读取设备属性并按规则文件顺序匹配。
kernel detects device
-> emits uevent with subsystem/action/devpath
-> udev loads sysfs attributes
-> udev evaluates matching rules
-> udev applies permissions, symlinks, tags, commands2. 匹配条件来自当前设备或父设备
常见 USB 规则写法是:
SUBSYSTEM=="usb", ATTR{idVendor}=="2207", ATTR{idProduct}=="0001", MODE="0660", GROUP="plugdev"这里:
SUBSYSTEM=="usb"匹配 USB 子系统设备。ATTR{idVendor}匹配当前 sysfs 设备节点上的idVendor属性。ATTR{idProduct}匹配当前 sysfs 设备节点上的idProduct属性。MODE="0660"设置权限位。GROUP="plugdev"设置设备节点所属组。
如果要匹配子设备,例如 /dev/ttyUSB* 或 /dev/video*,可能需要使用 ATTRS{} 匹配父设备链上的 USB 属性,而不是 ATTR{}。ATTR{} 看当前设备,ATTRS{} 可以沿父设备查找匹配属性,这是常见调试点。
3. 稳定命名通常需要比 VID/PID 更细
如果只按 VID/PID 创建软链接:
SYMLINK+="my-device"多台同型号设备同时存在时会冲突。更稳的规则通常还要加入:
ATTRS{serial}:设备提供稳定序列号时优先使用。ENV{ID_PATH}:按物理 USB 拓扑定位,例如固定端口。- interface number:区分复合设备中的不同接口。
这和 SN 与 Device ID 的边界类似:VID/PID 描述型号,serial、路径或业务 ID 才能进一步区分实例。
工程用途
- 给烧录器、调试板、串口、HID、USB 设备授予非 root 访问权限。
- 为不稳定的
/dev/ttyUSB*、/dev/video*建立稳定软链接。 - 多相机、多串口、多传感器系统中按 USB by-path 固定角色。
- 在设备接入时打标签,例如
TAG+="uaccess"让当前桌面用户获得访问权。 - 调试设备属性:用
udevadm info --attribute-walk --name=/dev/xxx找可匹配字段。
边界与常见坑
- udev 不是驱动:它不会让内核支持一个未知协议,只能在设备已被内核发现后处理权限、命名和动作。
- VID/PID 匹配不够唯一:多台同型号设备会共享 VID/PID,稳定定位要加 serial、interface 或 path。
ATTR{}与ATTRS{}容易混用:当前节点没有idVendor时,应检查父设备属性链。- 规则修改后要重新加载:常用
udevadm control --reload-rules,再重新插拔或触发udevadm trigger。 RUN+=不适合长任务:udev 触发脚本应短小,长期服务应交给 systemd。- 权限不是安全认证:给设备节点放权只解决本机访问控制,不证明设备可信。