отладка правил udev
Столкнулся тут с задачей: нужно было написать правило для udev, такое, чтобы стартовали программы (какие, сейчас не важно) при подключении измерительной карты к прибор. Соответственно, при отключении карты от прибора программы должны прибиваться.
Когда дело дошло до отладки, я обнаружил, что куда-то делся udev-monitor,
который раньше позволял мониторить появление и удаление устройств. Позже оказалось, что никуда он не пропал, а стал по-другому называться.
Теперь, чтобы запустить мониторинг нужно использовать:
$ udevadm monitor --udev
И будет счастье! ;)
Но ещё не полное. Ведь при отладке приходится убивать разъём и делать много телодвижений, вынимая и вставляя карту. Этого можно избежать, поскольку добавление устройства происходит после так называемого binding-а драйвера и подходящего к нему устройства. А для инициирования binding-a можно использовать маленький трюк.
Он заключается в следующем. Определяем, к какому драйверу подходит устройство, hotplug которого мы отлаживаем. «Подходящесть» драйвера к устройству определяется их именами
(см. сюда). Далее для симуляции выдёргивания/вставления устройства выполняем unbinding, а потом binding:
$ echo -n device_name > /sys/.../drivers/driver_name/unbind
После этой команды устройство пропадёт из системы. Будет выполнено правило
«remove» udev’ом.
$ echo -n device_name > /sys/.../drivers/driver_name/bind
После этой команды устройство cнова появится в системе. Будет выполнено правило «add» udev’ом.
Вот и всё.
А отлаживать происходящее в скриптах можно обычной связкой logger + syslogd.
И будет счастье ;)
Ну и ещё один трюк, в актуальности которого я, правда, сомневаюсь. Есть такая команда
$ udevadm test
,
которая позволяет симулировать появление/пропадание устройства. Её плюс в том, что она пишет, какие программы и скрипты запускает udev! Чтобы устранить сомнения насчёт того, выполняется ли вообще скрипт. Меня смутило только предупреждение в man’e относительно этой команды. А вообще она мне помогла :)
Вы бы реальный пример привели, а то не совсем понятно что именно значит device_name, где его искать, и многоточие в путях вводит в уныние.
А так спасибо, если честно то не знал о программной возможности переподключить устройство.
Да, согласен. Всё не так очевидно ;) Нужно понимать, как работает binding устройств и драйверов в ядре. Вот небольшая инструкция, которая может помочь.
У меня есть девайс arm-usb-ocd (отладчик). Подключаю его к компу по usb при запущенном udev monitore. Вот, что вижу в мониторе:
UDEV [1281595359.479667] add /devices/pci0000:00/0000:00:1d.0/usb2/usb_device/usbdev2.1 (usb_device)
UDEV [1281595359.521175] add /devices/pci0000:00/0000:00:1d.0/usb2/2-0:1.0 (usb)
UDEV [1281595359.523495] add /devices/pci0000:00/0000:00:1d.0/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81 (usb_endpoint)
UDEV [1281595359.879303] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2 (usb)
UDEV [1281595359.896482] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/usb_endpoint/usbdev2.123_ep00 (usb_endpoint)
UDEV [1281595359.915017] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0 (usb)
UDEV [1281595359.927947] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1 (usb)
UDEV [1281595359.929630] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/usb_endpoint/usbdev2.123_ep81 (usb_endpoint)
UDEV [1281595359.932820] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/usb_endpoint/usbdev2.123_ep02 (usb_endpoint)
UDEV [1281595359.936218] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/ttyUSB0 (usb-serial)
UDEV [1281595359.942481] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/usb_endpoint/usbdev2.123_ep83 (usb_endpoint)
UDEV [1281595359.945976] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/usb_endpoint/usbdev2.123_ep04 (usb_endpoint)
UDEV [1281595359.968245] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/usb_device/usbdev2.123 (usb_device)
UDEV [1281595359.982977] add /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/ttyUSB0/tty/ttyUSB0 (tty)
Нахожу там usb_device. К пути, который приведён в выводе udev monitor’a прибавляем приставку /sys. Получается:
/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-2/usb_device/usbdev2.123
Этот путь — это каталог, в котором:
$ ls /sys/devices/pci0000:00/0000:00:1d.0/usb2/usb_device/usbdev2.1
dev device power subsystem uevent
device — это symlink, который в себе содержит symlink на driver, к которому он приаттачен. Нужно запомнить, куда указывает этот симлинк, поскольку после уделения устройства драйвер по описанному алгоритму найти уже невозможно ;) В каталоге этого драйвера вот что:
$ ls /sys/devices/pci0000:00/0000:00:1d.0/usb2/usb_device/usbdev2.1/device/driver/
2-2 bind module uevent unbind usb1 usb2 usb3 usb4 usb5
Так вот, чтобы отключить устройство, нужно выполнить (под root’ом)
echo -n usb2 > /sys/devices/pci0000:00/0000:00:1d.0/usb2/usb_device/usbdev2.1/device/driver/unbind
В udev monitor’e будет видно, что происходит «remove»:
UDEV [1281595305.680487] remove /devices/pci0000:00/0000:00:1d.0/usb2/usb_device/usbdev2.1 (usb_device)
UDEV [1281595305.684690] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81 (usb_endpoint)
UDEV [1281595305.687069] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/usb_endpoint/usbdev2.122_ep81 (usb_endpoint)
UDEV [1281595305.689200] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/usb_endpoint/usbdev2.122_ep02 (usb_endpoint)
UDEV [1281595305.692701] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0 (usb)
UDEV [1281595305.694901] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/usb_endpoint/usbdev2.122_ep83 (usb_endpoint)
UDEV [1281595305.697029] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/usb_endpoint/usbdev2.122_ep04 (usb_endpoint)
UDEV [1281595305.703166] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/usb_endpoint/usbdev2.122_ep00 (usb_endpoint)
UDEV [1281595305.706028] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-0:1.0 (usb)
UDEV [1281595305.710336] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/usb_device/usbdev2.122 (usb_device)
UDEV [1281595305.733922] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/ttyUSB0/tty/ttyUSB0 (tty)
UDEV [1281595305.739520] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1/ttyUSB0 (usb-serial)
UDEV [1281595305.742798] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.1 (usb)
UDEV [1281595305.746287] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-2 (usb)
Чтобы вернуть в систему устройство, нужно выполнить echo -n «usb2» в bind того драйвера, путь которого был сохранён (см. выше).
В моём случае:
$ echo -n usb2 > /sys/bus/usb/drivers/usb/bind
Дальше смотрим в udev monitor.
;)
обнаружил тут такую штуку.
в ядре 2.6.35 у device’а появился атрибут remove
запись «1» в этот атрибут равносильная unbind ;)
так что driver искать не обязательно
Спасибо!))
рад был помочь!
оч. приятно, что мои труды кому-то пригодились ;)