在Linux系统中,USB串口设备(如CH340、FT232、PL2303等)插入时,系统会动态分配设备名(如ttyUSB0、ttyUSB1等),但设备名的分配顺序取决于插入时机,可能导致同一设备在不同时间插入时名称变化(如先插入的设备被识别为ttyUSB1,后插入的反而成为ttyUSB0),这种不确定性会影响依赖固定设备名的脚本、应用程序或服务(如串口通信程序、工业设备控制等),因此需要通过固定ttyUSBx设备名来解决这一问题,核心方法是利用udev(Linux设备管理器)创建规则,根据设备的唯一属性(如Vendor ID、Product ID、序列号等)绑定固定的设备名或符号链接。

获取USB串口设备的唯一属性
编写udev规则前,需先确定目标设备的唯一标识信息,避免与其他设备冲突,常用属性包括Vendor ID(厂商ID)、Product ID(产品ID)、序列号(Serial Number)及设备路径等,获取方法如下:
-
使用
lsusb命令识别设备
执行lsusb会列出所有USB设备,找到目标串口设备,记录其Vendor ID和Product ID(格式为idVendor:idProduct,如1a86:7523)。
示例输出:Bus 001 Device 005: ID 1a86:7523 QinHeng Electronics CH340 serial converter
此处
1a86为Vendor ID,7523为Product ID。 -
通过
udevadm获取详细信息
若多个设备同型号(Vendor ID和Product ID相同),需进一步区分,可通过序列号或设备路径,插入设备后,执行:udevadm info -a -n /dev/ttyUSB0 --query=all
在输出中查找
ATTRS{idVendor}、ATTRS{idProduct}、ATTRS{serial}(若有)等字段,记录设备的唯一属性。
示例关键输出:
ATTRS{idVendor}=="1a86" ATTRS{idProduct}=="7523" ATTRS{serial}=="1234567890abcdef"
编写udev规则固定设备名
udev规则文件存放在/etc/udev/rules.d/目录下,文件名需以.rules数字越小优先级越高(如99-usb-serial.rules),规则语法核心是通过SUBSYSTEM、ATTRS等条件匹配设备,再通过SYMLINK或NAME绑定固定名称。
基本规则语法
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="xxxx", SYMLINK+="my_device"
ACTION=="add":设备插入时触发;SUBSYSTEM=="tty":匹配tty设备(即串口设备);ATTRS{idVendor}和ATTRS{idProduct}:匹配设备的厂商和产品ID;SYMLINK+="my_device":创建固定名称的符号链接(如/dev/my_device指向实际设备/dev/ttyUSB0),推荐使用SYMLINK而非直接修改NAME,避免覆盖默认设备名导致兼容性问题。
多设备区分规则
若存在多个同型号设备,需通过序列号(ATTRS{serial})或设备路径(KERNELS)进一步区分:
- 通过序列号区分:
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{serial}=="1234567890abcdef", SYMLINK+="device_1" ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{serial}=="abcdef1234567890", SYMLINK+="device_2" - 通过设备路径区分(若设备插入不同物理端口):
ACTION=="add", SUBSYSTEM=="tty", KERNELS=="1-1.1", SYMLINK+="device_1" ACTION=="add", SUBSYSTEM=="tty", KERNELS=="1-1.2", SYMLINK+="device_2"
KERNELS可通过udevadm info -a -n /dev/ttyUSB0中的KERNELS字段获取。
设置设备权限(可选)
若需固定用户访问权限,可在规则中添加MODE或GROUP:
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="my_device", MODE="0666", GROUP="dialout"
MODE="0666":所有用户可读写;GROUP="dialout":将设备加入dialout组(默认串口用户组),需确保用户在该组内(可通过usermod -aG dialout $USER添加)。
加载并测试udev规则
- 重新加载udev规则
sudo udevadm control --reload-rules
- 触发规则生效
sudo udevadm trigger
- 验证设备名
拔插设备后,检查/dev/下是否出现固定符号链接(如/dev/my_device),并通过ls -l /dev/my_device确认指向实际设备(如/dev/ttyUSB0)。
示例输出:lrwxrwxrwx 1 root root 7 Dec 1 10:00 /dev/my_device -> ttyUSB0
USB串口设备属性总结表
| 属性名 | 获取方式 | 规则中示例 | 作用说明 |
|---|---|---|---|
| Vendor ID | lsusb或udevadm info |
ATTRS{idVendor}=="1a86" |
匹配设备厂商 |
| Product ID | lsusb或udevadm info |
ATTRS{idProduct}=="7523" |
匹配设备型号 |
| 序列号 | udevadm info(需设备支持) |
ATTRS{serial}=="1234567890" |
区分同型号不同设备 |
| 设备路径 | udevadm info(KERNELS字段) |
KERNELS=="1-1.1" |
匹配设备插入的物理USB端口 |
| 子系统 | 固定(串口设备为”tty”) | SUBSYSTEM=="tty" |
确保匹配串口设备 |
FAQs
Q1:为什么我的udev规则编写后没有生效?
A:可能原因包括:① 规则文件语法错误(可通过udevadm test /sys/class/tty/ttyUSBx测试);② 设备属性不匹配(如Vendor ID/Product ID写错);③ 未重新加载规则或触发udev(执行udevadm control --reload-rules和udevadm trigger);④ 规则文件名优先级过低(确保文件名数字小于默认规则,如99-xxx.rules),检查/var/log/syslog或journalctl -u udev查看udev日志,定位错误原因。

Q2:如何为多个同型号USB串口设备分别分配固定名称?
A:若设备支持序列号,优先通过序列号区分(如ATTRS{serial}=="xxx");若不支持序列号,可通过设备路径(KERNELS)区分(如插入到主板的USB端口1和端口2,路径分别为1-1.1和1-1.2),编写多条规则,每条规则匹配唯一属性并分配不同的SYMLINK名称,
# 设备1(插入端口1-1.1) ACTION=="add", SUBSYSTEM=="tty", KERNELS=="1-1.1", SYMLINK+="device_port1" # 设备2(插入端口1-1.2) ACTION=="add", SUBSYSTEM=="tty", KERNELS=="1-1.2", SYMLINK+="device_port2"
拔插设备后,通过ls -l /dev/device_port*验证是否正确绑定。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/31709.html