【udev重命名详细教程】放弃硬编码,从重命名开始

前言

  • 上一期我们在讲双雷达的时候使用过串口udev重命名,这一期我们详细讲一下背后的原理和具体查询过程

  • 本文包括:
    *

    1 串口udev重命名教程
    2 udev原理

1 串口udev重命名教程

1-1 串口查询
  • 查询串口
bash 复制代码
ls /dev/tty*
  • 通过插拔可以短暂确认本轮的临时串口号
1-2 串口信息确认
  • 查询串口的信息
bash 复制代码
dmesg | grep ttyUSB1
1-3 设备详细信息
  • 查询具体信息
    • -n /dev/ttyUSB1:代表 name(名称)
    • -a:代表"向上遍历设备树"
bash 复制代码
udevadm info -a -n /dev/ttyUSB1 | grep -E "{idVendor}|{idProduct}|KERNELS=="
  • 通过上述输出我们可以看到整个层级结构:
  • 第一层:软件虚拟层,这是 Linux 内核驱动(ch341 驱动)最终创建的设备节点名称。
bash 复制代码
KERNELS=="ttyUSB1"
  • 第二层:USB 接口层,代表 USB 设备的"配置1,接口0
bash 复制代码
KERNELS=="1-1.2.4:1.0"
  • 第三层:真正的目标硬件,KERNELS=="1-1.2.4"这是物理 USB 拓扑路径
    • 1a86:7523:这是南京沁恒(WCH)CH341 芯片的绝对唯一身份证号。不管你插在电脑的哪个口,这两个值都不会变。
bash 复制代码
KERNELS=="1-1.2.4"
ATTRS{idProduct}=="7523"
ATTRS{idVendor}=="1a86"
  • 第四层:上游 USB 集线器 Hub,这里我的32是经过拓展坞接到板子上的
bash 复制代码
KERNELS=="1-1.2"
ATTRS{idProduct}=="2813"
ATTRS{idVendor}=="2109"
KERNELS=="1-1"
ATTRS{idProduct}=="0610"
ATTRS{idVendor}=="05e3"
  • 第五层:主板根控制器(操作系统提供),这是你电脑主板上实际的 USB 控制器(根集线器)
bash 复制代码
KERNELS=="usb1"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
  • 第六层:最底层的硬件总线(硬核底层)
bash 复制代码
KERNELS=="xhci-hcd.2.auto"
KERNELS=="35100000.usb"
KERNELS=="35100000.usb3"
KERNELS=="35000000.hsio_apb"
KERNELS=="soc"
KERNELS=="platform"
1-4 编写 udev 规则
  • 通过上一节的信息确认,我们得知了不会变的设备物理id
bash 复制代码
KERNELS=="1-1.2.4"
ATTRS{idProduct}=="7523"
ATTRS{idVendor}=="1a86"
  • 这时候我们只需要修改udev规则文件即可
bash 复制代码
sudo nano /etc/udev/rules.d/99-stm32-ch341.rules
  • 把下述代码粘贴进去
bash 复制代码
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="stm32", MODE="0666"
1-5 重新加载udev规则
bash 复制代码
sudo udevadm control --reload-rules
sudo udevadm trigger
1-6 插拔验证
  • 我们重新查找
bash 复制代码
ls /dev/st*

2 udev原理

2-1 为什么需要 udev?
  • 在早期的 Linux 中,/dev 目录下的设备节点是静态的。这就导致了一个致命问题:"插拔风暴"
  • 假设你只有一个串口设备,它永远是 /dev/ttyUSB0,这没什么问题。
  • 但在我们的机器人开发中(比如双雷达 + STM32 底盘),如果你先插雷达,雷达可能抢占 ttyUSB0ttyUSB1;如果你先插 STM32,STM32 就变成了 ttyUSB0设备的命名完全取决于你插线的先后顺序。
  • 这会导致我们的 ROS launch 文件或代码配置极其脆弱,每次重启或换 USB 口都要改代码。udev 就是为了解决这个问题而诞生的------它负责在用户层动态管理设备,实现"按硬件身份固定名字"。

2-2 udev 的工作机制
  • udev 并不是一直在后台轮询(死循环检测)USB 口,它是事件驱动 的。核心流程如下:
    1. 内核发现硬件:当你插入 USB 设备时,Linux 内核的驱动程序(如 ch341)会检测到这一物理动作。
    2. 发送 uevent:内核会通过 Netlink 套接字,向用户空间广播一个"设备变更事件"。
    3. udev 守护进程接单 :后台运行的 udevd(udev 守护进程)监听到这个事件,拿到设备的信息。
    4. 规则匹配udevd 会按照字典顺序,遍历 /etc/udev/rules.d/ 目录下的所有 .rules 文件。
    5. 执行动作 :一旦匹配到某条规则(比如我们写的 99-stm32-ch341.rules),udev 就会执行规则里指定的动作(创建软链接、修改权限等)。

2-3 规则文件的底层逻辑
  • 我们在 1-4 节写的这行代码
bash 复制代码
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="stm32", MODE="0666"
  • 它可以分为两类关键字:匹配键(条件)赋值键(动作)
  • 匹配键(用 == 表示,必须全部满足才会触发)
    • SUBSYSTEM=="tty":告诉 udev "我只关心串口类设备"。如果你插了个 CH341 的鼠标(也是 1a86:7523,但属于 input subsystem),这条规则不会拦截它,防止误杀。
    • ATTRS{idVendor}=="1a86"ATTRS{idProduct}=="7523":精准狙击,对照前面讲的"设备树第三层",直接锁定这个具体的硬件。
  • 赋值键(用 +== 表示,触发后执行的操作)
    • SYMLINK+="stm32"+= 的意思是"追加一个别名"。udev 会在 /dev/ 下创建一个名为 stm32 的快捷方式,指向真实的 ttyUSBx。(注意:它不会抹除系统原本生成的 ttyUSB1,两者共存)。
    • MODE="0666"= 的意思是"强制赋值"。把该设备的权限改为 0666(即所有用户可读可写)。这样我们的普通用户(比如运行 ROS 节点的用户)就不需要每次都加 sudo 才能打开串口了。

2-4 关于"设备树层级"与规则的避坑指南
  • 结合我们在 1-3 节看到的六层结构,udev 在匹配 ATTRS{} 时,是允许跨层级向上查找的。
  • 为什么不能匹配第四层(Hub)? 如果你把规则写成 ATTRS{idVendor}=="2109"(扩展坞的 ID),那么只要这个扩展坞一通电,或者你往扩展坞上插个 U 盘,udev 都会试图执行动作,导致系统混乱。
  • 最佳实践 :写 udev 规则时,匹配条件要尽量贴近设备树的底层(即目标硬件本身那一层,通常包含 idVendoridProduct 的那一层),这样才能保证规则的唯一性和稳定性。

总结

  • 本文系统讲解了如何彻底解决Linux系统中多串口设备(如STM32)因插拔顺序导致命名随机变化的痛点;通过演示使用udevadm命令向上遍历设备树以精准提取芯片唯一硬件ID的全流程,并深入剖析udev基于事件驱动的底层匹配与赋值机制,最终实现了为设备创建固定的软链接与权限配置,确保了开发环境的绝对稳定。
  • 如有错误,欢迎指出!
  • 感谢你的观看
相关推荐
Cx330❀6 小时前
【MySQL基础】一文吃透“表的约束”:从 Null/Default 到主外键的终极安全法则
linux·服务器·数据库·c++·mysql·安全
程序员JerrySUN6 小时前
Jetson 刷机深度解析:flash.sh vs l4t_initrd_flash.sh(含安全与磁盘加密对比)
linux·网络·arm开发·安全·系统安全
会的东西有点杂6 小时前
ROS 2和ROS 1的比较
机器人
六点_dn7 小时前
Linux学习笔记-printf命令
linux·运维·算法
蜡台7 小时前
Linux Python 安装使用
linux·运维·服务器
酉鬼女又兒7 小时前
零基础入门 DeepSeek V4 Pro API 开发:从环境搭建、消息格式规范到翻译函数实战、少样本提示、多轮对话聊天机器人与常见报错全流程详解指南
大数据·网络·数据库·人工智能·macos·机器人·github
欧神附体1237 小时前
在虚拟机中添加网卡,修改网卡名并关闭SElinux
linux·服务器·网络
小顿的企业观察9 小时前
从人形机器人到AI销售智能体,AI正在重塑中企出海的底层逻辑
大数据·运维·人工智能·机器人·产品运营·制造
brave_zhao9 小时前
openEuler下安装tar包解压工具
linux·服务器·数据库
小宏运维有点菜9 小时前
JumpServer
linux·运维