docker --device 使用绝对设备路径,但因符号链接而失败

Deu*_*ina 6 usb symlink udev libusb-1.0 docker

我有一个USB GPIO设备,其中包含一些第三方驱动程序,我想在容器中与其进行交互。编译,在主机上运行良好。也可以编译,如果我通过--device=/dev/bus/usb/001/$NUM其中 $NUM 是插入设备时自动生成的路径,则可以在容器中正常工作;我猜想 udev 正在分配这个。但是我想要一个确定性的绑定点,所以我修改了 udev规则来分配一个符号链接:

SUBSYSTEM=="usb", ATTR{idVendor}=="09db", 
ATTR{idProduct}=="0075", MODE="0666", 
TAG+="uaccess", TAG+="udev-acl", 
SYMLINK+="mcc_daq"
Run Code Online (Sandbox Code Playgroud)

这给了我一个位于/dev/mcc_daqto的符号链接/dev/bus/usb/whatever。在主机上仍然可以正常工作。

但是,如果我运行:

docker run --rm -it \
        --device=/dev/mcc_daq \
        mcc_daq1
Run Code Online (Sandbox Code Playgroud)

我明白了

usb_device_find_USB_MCC: libusb_open failed.: No such file or directory 
Failure, did not find a USB 2408 or 2408_2AO!
Run Code Online (Sandbox Code Playgroud)

这是测试程序在找不到设备时输出的内容(使用libusb_get_device_descriptor)。

当我在容器中运行时,我得到的输出与使用 启动容器时的udevadm info -q all /dev/mcc_daq输出完全相同。但是,如果我将符号链接路径传递给docker,则无法查询绝对路径。 udevadm info -q all /dev/bus/usb/001/004--device=/.../004

udev 输出在主机系统上更加详细,我不确定这是否是问题或预期行为的一部分。我的直觉是缺少这些额外的条目意味着 libusb 可以找到设备,但找不到产品的供应商 ID。然而,udev 输出在容器中是相同的(无论是符号链接还是硬路径)这一事实让我对此产生疑问。

更新:新的有趣事实:当我在测试程序上运行 strace 时,我发现:

open("/dev/bus/usb/001/004", O_RDWR)    = -1 ENOENT (No such file or directory)
Run Code Online (Sandbox Code Playgroud)

所以这意味着驱动程序正在寻找../004,即使我安装了---device=/dev/mcc_daq。我不确定它从哪里获得这些信息。

简而言之,我认为 usingdocker run --device=/dev/symlink不会引入与使用硬路径相同的 udev 上下文,即使 的输出udevadm info是相同的。

主持人:udevadm info -q all /dev/mcc_daq

P: /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2
N: bus/usb/001/004
S: mcc_daq
E: BUSNUM=001
E: DEVLINKS=/dev/mcc_daq
E: DEVNAME=/dev/bus/usb/001/004
E: DEVNUM=004
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_8_2
E: ID_MODEL=USB-2408-2AO
E: ID_MODEL_ENC=USB-2408-2AO
E: ID_MODEL_ID=00fe
E: ID_PATH=pci-0000:00:14.0-usb-0:8.2
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_8_2
E: ID_REVISION=0101
E: ID_SERIAL=MCC_USB-2408-2AO_01DA523C
E: ID_SERIAL_SHORT=01DA523C
E: ID_USB_INTERFACES=:ffff00:
E: ID_VENDOR=MCC
E: ID_VENDOR_ENC=MCC
E: ID_VENDOR_FROM_DATABASE=Measurement Computing Corp.
E: ID_VENDOR_ID=09db
E: MAJOR=189
E: MINOR=3
E: PRODUCT=9db/fe/101
E: SUBSYSTEM=usb
E: TAGS=:uaccess:seat:udev-acl:
E: TYPE=255/255/0
E: USEC_INITIALIZED=19197013
Run Code Online (Sandbox Code Playgroud)

码头工人:udevadm info -q all /dev/mcc_daq

P: /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2
N: bus/usb/001/004
E: BUSNUM=001
E: DEVNAME=/dev/bus/usb/001/004
E: DEVNUM=004
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2
E: DEVTYPE=usb_device
E: DRIVER=usb
E: MAJOR=189
E: MINOR=3
E: PRODUCT=9db/fe/101
E: SUBSYSTEM=usb
E: TYPE=255/255/0
Run Code Online (Sandbox Code Playgroud)

码头工人:udevadm info -q all /dev/bus/usb/001/004

P: /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2
N: bus/usb/001/004
E: BUSNUM=001
E: DEVNAME=/dev/bus/usb/001/004
E: DEVNUM=004
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2
E: DEVTYPE=usb_device
E: DRIVER=usb
E: MAJOR=189
E: MINOR=3
E: PRODUCT=9db/fe/101
E: SUBSYSTEM=usb
E: TYPE=255/255/0
Run Code Online (Sandbox Code Playgroud)

Seb*_*ian 5

这次讨论中,我得出的结论是,如果您的docker run命令是您实际使用它的方式,您可以使用下面的 bash 替换并在工具“readlink”的帮助下进行解决方法:

docker run --rm -it \
        --device=$(readlink -f /dev/mcc_daq) \
        mcc_daq1
Run Code Online (Sandbox Code Playgroud)

但是,如果您像我一样使用 docker-compose,这种解决方法会稍微尴尬一些,因为我猜您需要对环境变量进行一些准备工作。

当然,此解决方法的问题之一是,如果重新插入设备,路径将无效。所以我想你必须重新启动容器..