首页 > 其他分享 >docker 容器中,当需要读取外接usb 设备,每次插拔 sub 设备,设备编号一直变化怎么办?

docker 容器中,当需要读取外接usb 设备,每次插拔 sub 设备,设备编号一直变化怎么办?

时间:2024-06-20 16:14:15浏览次数:24  
标签:插拔 sub -- dev 001 设备 root usb

docker 容器中,当需要读取外接usb 设备,每次插拔 sub 设备,设备编号一直变化怎么办?这会影响程序的读取。因此每次创建容器时候,设备编号就固定在 容器中了。比如:

在容器中运行:

root@h-pc:~/ros_ws# lsusb
Bus 002 Device 002: ID 174c:3074 ASMedia Technology Inc. ASM1074 SuperSpeed hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 031: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light
Bus 001 Device 030: ID 2bc5:0502  
Bus 001 Device 029: ID 2bc5:0403  
Bus 001 Device 028: ID 05e3:0610 Genesys Logic, Inc. 4-port hub
Bus 001 Device 002: ID 174c:2074 ASMedia Technology Inc. ASM1074 High-Speed hub
Bus 001 Device 005: ID 8087:0032 Intel Corp. 
Bus 001 Device 004: ID 26ce:01a2  
Bus 001 Device 003: ID 17ef:608c Lenovo 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

我们重新插拔 usb 设备后,设备编号 变为了 029 等等。

而 我们在容器中:

root@h-pc:~/ros_ws# ls -l /dev/bus/usb/001/
total 0
crw-rw-r-- 1 root root 189,  0 Jun 19 17:58 001
crw-rw-r-- 1 root root 189,  1 Jun 19 17:58 002
crw-rw-r-- 1 root root 189,  2 Jun 19 17:58 003
crw-rw-r-- 1 root root 189,  3 Jun 19 17:58 004
crw-rw-r-- 1 root root 189,  4 Jun 19 17:58 005
crw-rw-r-- 1 root root 189,  6 Jun 19 17:58 007
crw-rw-r-- 1 root root 189,  7 Jun 20 13:33 008
crw-rw-r-- 1 root root 189,  8 Jun 20 13:33 009
crw-rw-r-- 1 root root 189, 10 Jun 19 17:58 011

发现并没有这个设备编号。这会导致启动 launch 文件时候报错:

[ INFO] [1718863863.439322079]: Query device
[ INFO] [1718863863.539486552]: Device connected: (name, Astra) (uri, 2bc5/0403@1/29) (vendor, Orbbec)
[ INFO] [1718863863.539548038]: Trying to open device: 2bc5/0403@1/29
[ INFO] [1718863863.639677743]: OBCameraNodeFactory::onDeviceConnected Open device start
[ INFO] [1718863863.642548470]: OBCameraNodeFactory::onDeviceConnected Open device done, STATUS 4099
[ERROR] [1718863863.642597179]: Failed to open device: 2bc5/0403@1/29 	Could not open "2bc5/0403@1/29": USB device not found!

解释:Bus 001 Device 026: ID 2bc5:0403 分别都是什么意思?

lsusb 命令的输出中,每行表示一个已连接的 USB 设备。以下是每个部分的含义:

详细说明

  1. Bus 001:
    表示设备连接到的 USB 总线。USB 端口可以分布在多个总线(bus)上,每个总线有一个编号。这里,设备连接到总线编号为 001 的 USB 总线上。
  2. Device 026:
    表示设备在该总线上的设备编号。每个连接到同一总线的设备都有一个唯一的编号。这里,该设备的编号为 026。
  3. ID 2bc5:0403:
    表示设备的供应商 ID 和产品 ID。这两个值用于唯一标识设备的类型和制造商。
    2bc5: 供应商 ID (Vendor ID),表示设备的制造商。这里,2bc5 是 Orbbec 的供应商 ID。
    0403: 产品 ID (Product ID),表示特定型号的设备。这里,0403 是 Orbbec Astra 的产品 ID。

检查设备信息
你可以使用 lsusb -v 获取详细的设备信息。lsusb -v 命令输出非常详细,包含了设备的各种描述符信息。

lsusb -v -s 001:026

其中 -s 001:026 指定总线编号和设备编号,可以替换成实际的编号。

root@h-pc:~/ros_ws# ls /dev/bus/usb
001  002

检查usb 总线是否存在。


让我们重新梳理下我们遇到的问题:

这个问题是我在 容器 中 使用 usb 设备遇到的问题,接上回:https://www.cnblogs.com/odesey/p/18256384

问题:

假设我已经启动了一个容器了,但是我把 usb 设备进行了 插拔,设备编号发生了改变。即:

在容器内: ls /dev/bus/usb/001/026
ls: cannot access '/dev/bus/usb/001/026': No such file or directory
在宿主机:ls -l /dev/bus/usb/001/026
crw-rw-r-- 1 root root 189, 25 6月 20 13:53 /dev/bus/usb/001/026在容器内: ls /dev/bus/usb/001/026
ls:无法访问“/dev/bus/usb/001/026”:没有这样的文件或目录
在宿主机:ls -l /dev/bus/usb/001/026
crw-rw-r-- 1 根根 189, 25 6月 20 13:53 /dev/bus/usb/001/026

容器内只有:

ls /dev/bus/usb/001
001 002 003 004 005 007 008 009 011ls /dev/总线/usb/001
001 002 003 004 005 007 008 009 011

这是怎么回事呢?

解决:

在你将 USB 设备插拔后,宿主机会分配一个新的设备编号,而 Docker 容器启动时仅映射了当时存在的设备编号。这导致了容器内不能访问新的设备编号对应的设备文件。

以下是如何解决这个问题的几种方法:

方法 1: 重新启动容器
最简单的方法是重新启动 Docker 容器,使其重新映射当前所有的 USB 设备:

docker restart <container_name>

方法 2: 使用 --device-cgroup-rule
使用 --device-cgroup-rule 来允许容器访问任何 USB 设备,而不是特定的设备文件:

docker run --device-cgroup-rule='c 189:* rmw' -it --name ros_container ubuntu:18.04 /bin/bash

这将允许容器访问所有的 USB 设备,即使设备编号发生变化。

方法 3: 使用 --privileged 模式
--privileged 模式允许容器访问主机上的所有设备,这也解决了 USB 设备编号变化的问题:

docker run --privileged -it --name ros_container ubuntu:18.04 /bin/bash

方法 4: 使用 --device 映射整个 USB 总线
需要创建容器时候使用,这种方法确保所有设备在插拔后仍然可访问:

docker run --device=/dev/bus/usb -it --name ros_container ubuntu:18.04 /bin/bash

方法 5: 重新映射设备到正在运行的容器
如果不想重启容器,可以使用 docker exec 命令将新的设备映射到正在运行的容器。首先找到设备的路径:

在宿主机上运行以下命令以确定新设备路径:

ls -l /dev/bus/usb/001/

然后,将新设备路径映射到容器内:

docker exec -it ros_container bash -c "mount --bind /dev/bus/usb /dev/bus/usb"

方法 6: 使用 Udev 规则和固定设备路径
确保在 Udev 规则中创建固定的符号链接,以便在设备插拔后路径不变。例如:

  1. 创建 Udev 规则:

编辑或创建 /etc/udev/rules.d/99-usb-devices.rules 文件,添加以下内容:

# Orbbec Astra camera
SUBSYSTEM=="usb", ATTR{idProduct}=="0403", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_pro"

# IMU device (假设供应商 ID 和产品 ID 为 1234 和 5678)
SUBSYSTEM=="usb", ATTR{idProduct}=="5678", ATTR{idVendor}=="1234", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="imu_device"
  1. 重新加载 Udev 规则:

    sudo udevadm control --reload-rules
    sudo udevadm trigger

  2. 验证符号链接:

插入设备后,验证符号链接是否创建成功:

ls -l /dev/astra_pro
ls -l /dev/imu_device
  1. 启动 Docker 容器时映射这些符号链接:

    docker run --device=/dev/astra_pro --device=/dev/imu_device -it --name ros_container ubuntu:18.04 /bin/bash

方法 7: 动态添加设备到容器

通过以下命令动态添加设备到已经运行的容器中:

docker update --device-add /dev/bus/usb/001/026 <container_name>

总结
为了避免每次插拔 USB 设备后重新启动容器或手动重新映射设备,最推荐的方法是使用 --device=/dev/bus/usb 或 --privileged 模式启动容器。这两种方法都可以确保容器能够访问所有 USB 设备,而不受设备编号变化的影响。如果你更注重安全性,可以结合 Udev 规则为设备创建固定的符号链接。


首先,我们不想重新创建一个容器,因此:方法 2、3、4 不再适用。

方法1 值得推荐。

方法5 看起来也不错。

方法6 Udev 不能在 容器内执行。我们需要在宿主机执行该操作。然后在启动容器时候就可以加载进去了。

我们就暂时使用 方法1 吧。


https://www.cnblogs.com/odesey/p/18256384

在容器中 执行脚本: ./scripts/create_udev_rules
报错:

udev does not support containers, not started

在宿主机下:

  1. 那我们把 src/ros_astra_camera/56-orbbec-usb.rules 该文件 copy 到宿主机下:

    sudo cp 56-orbbec-usb.rules /etc/udev/rules.d/

  2. 重新加载 Udev 规则:

    sudo udevadm control --reload-rules
    sudo udevadm trigger

  3. 验证符号链接:

插入设备后,验证符号链接是否创建成功:

ls -l /dev/astra_pro
lrwxrwxrwx 1 root root 15 6月  20 15:41 /dev/astra_pro -> bus/usb/001/029

ls -l /dev/astrauvc
lrwxrwxrwx 1 root root 15 6月  20 15:41 /dev/astrauvc -> bus/usb/001/030

然后我们重启容器:

docker restart <container_name>

在容器内:

/dev/astra_pro 和 /dev/astrauvc我们依旧找不到

不行我们就做个软链接吧:

ln -s bus/usb/001/029 /dev/astra_pro
ln -s bus/usb/001/030 /dev/astrauvc

后面有问题再说。

我们打包容器为镜像后,再启动容器这些问题都可以解决了。

标签:插拔,sub,--,dev,001,设备,root,usb
From: https://www.cnblogs.com/odesey/p/18258851

相关文章

  • BOSHIDA DC/AC电源模块:为通信设备提供稳定的电力供应
    BOSHIDADC/AC电源模块:为通信设备提供稳定的电力供应在现代通信系统中,稳定可靠的电力供应是确保信息传输连续性和服务质量的关键因素之一。DC/AC电源模块作为通信设备能源管理的核心组件,扮演着至关重要的角色。它不仅负责将输入的直流电(DC)转换为交流电(AC),以满足不同通信设备的供电......
  • yolov8搭配GPU环境,并且解决GPU环境下设备运行报错问题
    1.GPU1.1GPU简介    GPU,即图形处理单元,是专为图形渲染而设计的处理器。其独特的并行计算能力使得它在处理大规模数据和复杂图形时表现出色。GPU不仅在游戏和虚拟现实领域发挥着关键作用,还广泛应用于深度学习、物理模拟和通用计算等领域。通过数以千计的核心,GPU能够......
  • 【usb设备端口异常】——使用ls /dev/video*查看设备号时出现报错:ls:无法访问‘/dev/v
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、ls:无法访问'/dev/video*':没有那个文件或目录1.问题描述2.原因分析3.解决方法总结前言一、ls:无法访问’/dev/video*':没有那个文件或目录使用的这款USB摄像头,厂家说是免驱......
  • 一文看懂怎么快捷、安全地实现制造设备数据传输
    制造设备在生产过程中会产生多种类型的数据,这些数据对于设备监控、维护以及生产流程的优化至关重要。以下是制造设备可能产生的数据:1.生产任务类数据生产计划及执行数据、每个工位的生产工单、工单的生产开始时间、中间暂停时间、生产结束时间、每个加工工步的工时消耗信息、......
  • 【漏洞复现】Zyxel NAS设备 setCookie 未授权命令注入漏洞(CVE-2024-29973)
    0x01产品简介Zyxel-NAS是指由ZyxelCommunicationsCorporation(合勤科技股份有限公司)开发和生产的网络附加存储(NetworkAttachedStorage,简称NAS)设备。NAS是一种专门用于存储和共享文件的设备,它通过网络连接到计算机、服务器或其他设备,提供集中式的文件存储和访问功能......
  • 设备树下的platform驱动编写
    文章目录前言一、platform是什么?二、编写步骤1.在设备树中创建设备节点2.注意兼容属性3.编写platform驱动总结前言基于总线、设备和驱动这样的驱动框架,Linux内核提出来platform这个虚拟总线,相应的也有platform设备和platform驱动。一、platform是什么?......
  • Cisco ASAv 9.20.2.22 Interim - 思科自适应安全虚拟设备 (ASAv)
    CiscoASAv9.20.2.22Interim-思科自适应安全虚拟设备(ASAv)CiscoAdaptiveSecurityVirtualAppliance(ASAv)请访问原文链接:https://sysin.org/blog/cisco-asav/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org思科自适应安全虚拟设备(ASAv):跨物理和虚拟环......
  • Cisco ASA 9.20.2.22 Interim - 思科自适应安全设备 (ASA) 软件
    CiscoASA9.20.2.22Interim-思科自适应安全设备(ASA)软件CiscoAdaptiveSecurityAppliance(ASA)请访问原文链接:https://sysin.org/blog/cisco-asa/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org思科自适应安全设备(ASA)软件成熟的防火墙和网络安全平......
  • 【操作系统】实验九 设备驱动程序设计
    一、实验目的分析一个典型的块设备RAM-DISK的驱动程序,学习编写设备驱动程序的一般过程。将这个RAM-DISK的程序改造成为U盘的驱动程序,并通过它来使用你的U盘。二、实验内容仔细阅读上一节中radimo的源代码,将radimo驱动程序改写成为一个U盘驱动程序。在检查时,你需要当场独......
  • Profibus转Modbus网关帮助PLC实现智能激光设备通讯
    一、前言Profibus协议转Modbus协议网关模块(XD-MDPB100)是一种工业通信协议转换设备,用于实现Profibus协议与Modbus协议之间的转换。Profibus转Modbus网关在工业自动化系统中具有广泛的应用,它解决了不同协议设备之间的通信问题。本文将深入探讨PLC通过Profibus转Modbus网关与激光设......