docker --device работает с абсолютным путем к устройству, не работает с символической ссылкой - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть устройство 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"

И это дает мне символическую ссылку от /dev/mcc_daq до /dev/bus/usb/whatever.По-прежнему работает нормально на хосте.

Но, если я запускаю с:

docker run --rm -it \
        --device=/dev/mcc_daq \
        mcc_daq1

, я получаю

usb_device_find_USB_MCC: libusb_open failed.: No such file or directory 
Failure, did not find a USB 2408 or 2408_2AO!

, то есть то, что тестовая программа выплевывает , когда можетне могу найти устройство (использует libusb_get_device_descriptor ).

Когда я запускаю в контейнере udevadm info -q all /dev/mcc_daq, я получаю точно такой же вывод, как и udevadm info -q all /dev/bus/usb/001/004, когда запускаю контейнер с --device=/.../004.Однако, если я передаю путь символической ссылки в Docker, я не могу запросить абсолютный путь.

Вывод udev более подробный на хост-системе, я не уверен, является ли это частью проблемы или ожидаемого поведения.Моя интуиция заключается в том, что отсутствие этих дополнительных записей означает, что libusb может найти устройство, но не может найти идентификатор поставщика продукта.Однако тот факт, что вывод udev в контейнере одинаков (независимо от символической ссылки или жесткого пути), заставляет меня усомниться в этом.

Обновление : новый забавный факт: когда я запускаю strace в тестовой программе, я нахожу:

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

Так что это означает, что драйвер ищет ../004хотя я смонтировал ---device=/dev/mcc_daq.Я не уверен, где он получает эту информацию.

Короче говоря, я думаю, что использование docker 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

Докер: 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

Докер: 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

1 Ответ

0 голосов
/ 22 февраля 2019

Из этого обсуждения Я пришел к выводу, что если ваша команда docker run соответствует тому, как вы на самом деле ее используете, вы можете обойти ее, используя нижеизложенный раздел bash, которому помогает инструмент readlink:

docker run --rm -it \
        --device=$(readlink -f /dev/mcc_daq) \
        mcc_daq1

Однако, если вы используете docker-compose, как я, этот обходной путь становится немного более неловким, потому что вам нужно будет выполнить некоторые подготовительные манипуляции с переменными окружения Я думаю.

Один изпроблемы с этим обходным путем, конечно, в том, что если вы подключите устройство заново, путь будет неверным.Таким образом, вам придется перезапустить контейнер, я думаю ..

...