асинхронные уведомления и udev

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

асинхронные уведомления и udev

Непрочитанное сообщение Olej » 27 окт 2012, 10:37

Понадобилось мне поразбираться (сделать для своих тестов) асинхронные уведомления из ядра Linux в свой пользовательский процесс. То, на чём работает udev и динамическая система devfs.

А заодно, раз уж выпала такая оказия, уточниться в деталях как работает udev.
Вот есть здесь на сайте свеже выложенный перевод Некоторые замечательные правила и примеры использования udev. Никаких "замечательных" правил там не ищите (статья довольно поверхностная) ... и вообще удивляет, что недавно написанная (28 Июня 2012 г. - это дата написания, а не перевода) статья описывает многие совершенно устаревшие команды, например... И тем не менее, для "освежить в памяти" сами основы udev вполне годится:
Служба udevd слушает netlink-сокет в ожидании событий, генерируемых ядром при подключении или отключении устройства. Вы можете наблюдать за этими событиями при помощи команды udevmonitor - запустите ее, подключите USB-устройство, например, flash-накопитель, и отключите его (в новейших дистрибутивах может не быть программы udevmonitor - в этом случае используйте udevadm.)
Для устройств, использующих горячее подключение, udevd принимает события ядра при помощи D-Bus, после чего получает атрибуты нового устройства из файловой системы /sys и применяет правила в зависимости от атрибутов - после этого создается файл устройства в файловой системе /dev. Udev также позволяет подгружать предназначенные для этого драйверы устройств при помощи механизма "modalias".
По поводу D-Bus здесь тоже выложен совершенно недавно перевод Разбираемся с D-BUS статьи, написанной Р.Лав (вот это отличная публикация, вполне достаточная для первого поверхностного представления о D-Bus).
Каждое событие уровня событий ядра моделируется таким образом, что в качестве инициатора приводится путь в файловой системе sysfs. Таким образом, события выглядят как инициированные объектами ядра. Пути из файловой системы sysfs легко приводятся к путям объектов D-BUS, связывая уровень событий ядра и систему D-BUS естественным образом. Уровень событий ядра был впервые представлен в ядре версии 2.6.10-rc1.
Вот этих зацитированных мной фраз уже достаточно для представления о полной логике работы системы udev, которая с внешней стороны пользователя выглядит мудрёной и загадочной.

netlink (PF_NETLINK) - очень старая выдумка в Linux, начиная с ядра 2.2, но которая очень мало описана, особенно о своём API использования из программного кода. Это такой "локальный сетевой сокет", используемый для посылки сообщений между ядром и пользовательскими процессами. Кой-какая информация может быть почерпнута из man-ов и пересказов man-ов: netlink, PF_NETLINK - установка связи между ядром и пользователем , Протокол netlink в Linux ... Но главным образом, кому будет нужно, придётся разгребаться с заголовочными файлами, кодом ядра и комментариями в коде там и там :-(

Население использует netlink для слежения (нотификации за изменениями) в сетевой системе (интерфейсы, аблица роутинга, ...), выложено несколько публикаций с примерами кода на этот счёт ... вот например Простой монитор сетевых интерфейсов Linux, с помощью netlink.
14 июня 2011
Из таких публикаций можно почерпнуть подсказки прямо из их кода... Пишущие подобные заметки тоже замечают все:
К сожалению, у библиотеки оказался не особо удобный и довольно сложный API, требовавший совершать множество непонятных действий. Особого веселья добавляло практически полное отсутствие документации и вообще любых материалов на эту тему.
Вот и интересует меня состояние дел с этими механизмами:
- для получения в свой процесс асинхронных уведомлений из ядра о происходящих там событиях;
- для отправки из кода своих модулей ядра нотификации пользовательским процессам;

По части udev ... он меня сейчас не сильно занимает, но это самая известная и самая крупная система, работающая на асинхронных уведомлениях ... Интересны именно сами принципы, которые они там используют. Но, может, и с ней будет случай и время разобраться детально, вплоть до их правил составления правил ;-) .

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 27 окт 2012, 11:02

Демоны системы udev:

Код: Выделить всё

bash-4.2$ ps -AF | grep udev
root       320     1  0  1292  1980   1 09:41 ?        00:00:00 /usr/lib/udev/udevd
root       711   320  0  1291  1400   1 09:41 ?        00:00:00 /usr/lib/udev/udevd
root       712   320  0  1291  1396   0 09:41 ?        00:00:00 /usr/lib/udev/udevd
olej      2751  2727  0  1193   772   1 10:02 pts/2    00:00:00 grep udev
Мне не совсем понятно почему их должно работать в системе 3 ... , но оставим это на потом.
Olej писал(а): Вот этих зацитированных мной фраз уже достаточно для представления о полной логике работы системы udev, которая с внешней стороны пользователя выглядит мудрёной и загадочной.
Вот так вот можно наблюдать как "посыпятся" сообщения через netlink:

Код: Выделить всё

bash-4.2$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
...
... при подключении, например, USB-флешки:

Код: Выделить всё

KERNEL[12742.192429] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb)
KERNEL[12742.192564] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 (usb)
UDEV  [12742.366940] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb)
KERNEL[12742.604210] add      /module/usb_storage (module)
KERNEL[12742.605523] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6 (scsi)
KERNEL[12742.605580] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/scsi_host/host6 (scsi_host)
KERNEL[12742.605646] add      /bus/usb/drivers/usb-storage (drivers)
UDEV  [12742.606235] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 (usb)
UDEV  [12742.675950] add      /module/usb_storage (module)
UDEV  [12742.677113] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6 (scsi)
UDEV  [12742.677490] add      /bus/usb/drivers/usb-storage (drivers)
UDEV  [12742.678661] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/scsi_host/host6 (scsi_host)
KERNEL[12743.611356] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0 (scsi)
UDEV  [12743.612540] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0 (scsi)
KERNEL[12743.613105] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0 (scsi)
KERNEL[12743.613186] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0 (scsi_disk)
KERNEL[12743.613263] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0 (scsi_device)
UDEV  [12743.614485] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0 (scsi)
KERNEL[12743.615149] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2 (scsi_generic)
UDEV  [12743.616440] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0 (scsi_device)
KERNEL[12743.616719] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0 (bsg)
KERNEL[12743.617652] add      /devices/virtual/bdi/8:16 (bdi)
UDEV  [12743.619151] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2 (scsi_generic)
UDEV  [12743.619745] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0 (bsg)
UDEV  [12743.620714] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0 (scsi_disk)
UDEV  [12743.621396] add      /devices/virtual/bdi/8:16 (bdi)
KERNEL[12743.682441] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb (block)
KERNEL[12743.682509] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb1 (block)
KERNEL[12743.682555] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb2 (block)
KERNEL[12743.682599] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb3 (block)
UDEV  [12744.016104] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb (block)
UDEV  [12744.036929] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb2 (block)
UDEV  [12744.111236] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb3 (block)
UDEV  [12744.174081] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb1 (block)
KERNEL[12744.828802] add      /module/nls_utf8 (module)
UDEV  [12744.829521] add      /module/nls_utf8 (module)
... и при её отключении:

Код: Выделить всё

KERNEL[12838.855048] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0 (bsg)
KERNEL[12838.855496] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2 (scsi_generic)
KERNEL[12838.855541] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0 (scsi_device)
KERNEL[12838.855577] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0 (scsi_disk)
KERNEL[12838.855756] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb3 (block)
KERNEL[12838.855981] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb2 (block)
KERNEL[12838.856235] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb1 (block)
KERNEL[12838.856437] remove   /devices/virtual/bdi/8:16 (bdi)
KERNEL[12838.856738] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb (block)
KERNEL[12838.856785] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0 (scsi)
KERNEL[12838.856821] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/scsi_host/host6 (scsi_host)
KERNEL[12838.856856] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6 (scsi)
UDEV  [12838.859478] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0 (bsg)
KERNEL[12838.859539] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 (usb)
UDEV  [12838.859584] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2 (scsi_generic)
UDEV  [12838.859732] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb2 (block)
UDEV  [12838.859780] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0 (scsi_device)
KERNEL[12838.859983] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb)
UDEV  [12838.860994] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb3 (block)
UDEV  [12838.862846] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0 (scsi_disk)
UDEV  [12838.863679] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb1 (block)
UDEV  [12838.863719] remove   /devices/virtual/bdi/8:16 (bdi)
UDEV  [12838.865890] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0/block/sdb (block)
UDEV  [12838.866498] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/scsi_host/host6 (scsi_host)
UDEV  [12838.867474] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6/target6:0:0/6:0:0:0 (scsi)
UDEV  [12838.868164] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host6 (scsi)
UDEV  [12838.868757] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 (usb)
UDEV  [12838.869927] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb)
KERNEL[12838.974538] remove   /host6/target6:0:0 (scsi)
UDEV  [12838.976357] remove   /host6/target6:0:0 (scsi)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 27 окт 2012, 19:07

Olej писал(а): Вот так вот можно наблюдать как "посыпятся" сообщения через netlink:
А для отработки уведомлений от ядра, с атрибутами-переменными, которые и использует в своих правилах udev, команда эта должна выглядеть так:

Код: Выделить всё

bash-4.2$ udevadm monitor --env
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
...
Только при этом вывод становится чудовищно большой - каждая срочка показанного раньше вывода разворачивается в полный набор атрибутов с значениями. Вот чем становится при этом одна 1-я строчка сообщений от ядра при подключении всё той же (можно сравнить) USB-флеш:

Код: Выделить всё

KERNEL[28414.391527] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb)
ACTION=add
BUSNUM=001
DEVNAME=/dev/bus/usb/001/009
DEVNUM=009
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4
DEVTYPE=usb_device
MAJOR=189
MINOR=8
PRODUCT=1307/163/100
SEQNUM=2407
SUBSYSTEM=usb
TYPE=0/0/0
Это как-раз самое то, чтобы создавать правила udev реакции на нотификации.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 27 окт 2012, 19:21

Olej писал(а):выложено несколько публикаций с примерами кода на этот счёт ... вот например Простой монитор сетевых интерфейсов Linux, с помощью netlink.
Вот этот проект (для экспериментов), чуть-чуть подчищенный для избежания warnings (не люблю ;-) ), возможно это из-за различий версии ядра или дистрибутива:
monitor.tgz
(6.68 КБ) 728 скачиваний
Но здесь я хочу собрать полезные URL, которые буду использовать при написании своих кодов (позже буду дополнять):

Относительно netlink-нотификации:

- Использование netlink для определения изменения маршрутов ipv6 в Linux.
5 СЕНТЯБРЯ 2011 Г.
- ещё один пример кода сетевой нотификации, возможно и от того автора, что показанный выше пример, по стилю очень похоже ... не знаю.

Относительно udev, как он использует нотификацию, и составления его правил

- Управление устройствами с помощью udev
2 февраля 2010 г.
Эта статья перевод 19-ой главы OpenSUSE Reference Guide, которое можно скачать в PDF-формате или просто посмотреть в формате html через браузер здесь.
- очень хорошее краткое описание, содержащее много приятных деталей.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 28 окт 2012, 01:29

Olej писал(а): - для получения в свой процесс асинхронных уведомлений из ядра о происходящих там событиях;
Конечно, самый простой способ получать асинхронные уведомления о hot-plug устройствах в свой процесс это:
- использовать непосредственно udevd ...
- записав в его правилах выполнение некоторой программы уведомления (скрипта)
- отправляющего по IPC уведомление в уже известный этой программе целевой процесс.

Это неэффективно, но это реакция на разовые редкие события, здесь эффективность мало что значит. Зато это просто + реализуется крайне быстро!

P.S. Это очень напоминает аналогию:
- вызов дочернего процесса посредством system() или popen() ...
- вместо вызовов fork() + exec();
- не эффективно по выполнению, в десятки раз менее трудоёмко по коду.

Я писал раньше разные правила udev, имею некоторый опыт ... , но не писал правил запуска дополнительных программ. И здесь пришлось повозиться :-( :

В итоге (это всё на подключение той же USB-флешки):

1. правила (2 - на подключение и выключение) - создал файл:

Код: Выделить всё

[root@notebook udev]# 
[root@notebook rules.d]# cat /etc/udev/rules.d/998-my-udev.rules  
SUBSYSTEM=="usb", ACTION=="add", RUN+="/lib/udev/_my_add.sh $attr{idVendor}:$attr{idProduct} %p %N"

SUBSYSTEM=="usb", ACTION=="remove", RUN+="/lib/udev/_my_rem.sh $attr{idVendor}:$attr{idProduct} %p %N"
2. скрипты /lib/udev/_my_add.sh & /lib/udev/_my_rem.sh, на которые ссылаются правила:

Код: Выделить всё

[root@notebook udev]# cat /lib/udev/_my_add.sh
#!/bin/bash
/usr/bin/logger ====== ADD $1 $2 $3 $4 ======

Код: Выделить всё

[root@notebook udev]# cat /lib/udev/_my_rem.sh
#!/bin/bash
/usr/bin/logger ====== REM $1 $2 $3 $4 ======
А теперь сразу, пока не забыл ;-) , почему "пришлось попотеть":
- пути запускаемых скриптов должны указываться полностью и абсолютно... никакой поиск $PATH не работает, да они и запускаются из неизвестного окружения (udevd);
- пути размещения могут быть любыми, /lib/udev/ - это только традиция, но должны быть прописаны полностью;
- если в скрипте не указан интерпретатор (#!/bin/bash) то это критическая ошибка, ничего не работает ... никакой флаг исполнимости 'x' на файле здесь не помогает...
- относительно пути запуска команды стандартной /usr/bin/logger (и любых других) то же самое: путь должен указываться полностью и абсолютно;
- ну и конечно, не могут здесь указываться команды, осуществляющие любой вывод на терминал - запуск из окружения демона, никакого терминала не существует...
Всё это соблюсти достаточно противно! ;-)

3. Проверяем ... просто втыкаем и вытыкаем USB-флешку и смотрим нотификации, попадающие в наш скрипт... Смотрим в логе:

Код: Выделить всё

[root@notebook udev]# tail -n 34 /var/log/messages
Oct 28 00:45:52 notebook kernel: [54278.686176] usb 1-4.4: new high-speed USB device number 24 using ehci_hcd
Oct 28 00:45:52 notebook kernel: [54278.763028] usb 1-4.4: New USB device found, idVendor=1307, idProduct=0163
Oct 28 00:45:52 notebook kernel: [54278.763038] usb 1-4.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Oct 28 00:45:52 notebook kernel: [54278.763044] usb 1-4.4: Product: USB Mass Storage Device
Oct 28 00:45:52 notebook kernel: [54278.763049] usb 1-4.4: Manufacturer: USBest Technology
Oct 28 00:45:52 notebook kernel: [54278.763054] usb 1-4.4: SerialNumber: 00000000000003
Oct 28 00:45:52 notebook kernel: [54278.765052] scsi22 : usb-storage 1-4.4:1.0
Oct 28 00:45:52 notebook udevd[320]: specified group 'plugdev' unknown
Oct 28 00:45:52 notebook mtp-probe: checking bus 1, device 24: "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4"
Oct 28 00:45:52 notebook mtp-probe: bus: 1, device: 24 was not an MTP device
Oct 28 00:45:52 notebook logger: ====== ADD 1307:0163 /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 /dev/bus/usb/001/024 ======
Oct 28 00:45:52 notebook logger: ====== ADD : /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 ======
Oct 28 00:45:53 notebook kernel: [54279.769716] scsi 22:0:0:0: Direct-Access     Ut163    USB2FlashStorage 0.00 PQ: 0 ANSI: 2
Oct 28 00:45:53 notebook kernel: [54279.771708] sd 22:0:0:0: Attached scsi generic sg2 type 0
Oct 28 00:45:53 notebook kernel: [54279.776152] sd 22:0:0:0: [sdb] 1974271 512-byte logical blocks: (1.01 GB/963 MiB)
Oct 28 00:45:53 notebook kernel: [54279.777058] sd 22:0:0:0: [sdb] Write Protect is off
Oct 28 00:45:53 notebook kernel: [54279.777909] sd 22:0:0:0: [sdb] Asking for cache data failed
Oct 28 00:45:53 notebook kernel: [54279.777916] sd 22:0:0:0: [sdb] Assuming drive cache: write through
Oct 28 00:45:53 notebook kernel: [54279.782683] sd 22:0:0:0: [sdb] Asking for cache data failed
Oct 28 00:45:53 notebook kernel: [54279.782691] sd 22:0:0:0: [sdb] Assuming drive cache: write through
Oct 28 00:45:53 notebook kernel: [54279.842176]  sdb: sdb1 sdb2 sdb3
Oct 28 00:45:53 notebook kernel: [54279.846542] sd 22:0:0:0: [sdb] Asking for cache data failed
Oct 28 00:45:53 notebook kernel: [54279.846551] sd 22:0:0:0: [sdb] Assuming drive cache: write through
Oct 28 00:45:53 notebook kernel: [54279.846558] sd 22:0:0:0: [sdb] Attached SCSI removable disk
Oct 28 00:45:53 notebook udisksd[1138]: Mounted /dev/sdb1 at /run/media/olej/RFRemix-17-i686-Live-GNOME on behalf of uid 1000
Oct 28 00:46:53 notebook dbus-daemon[680]: dbus[680]: [system] Activating service name='org.freedesktop.PackageKit' (using servicehelper)
Oct 28 00:46:53 notebook dbus[680]: [system] Activating service name='org.freedesktop.PackageKit' (using servicehelper)
Oct 28 00:46:53 notebook dbus-daemon[680]: dbus[680]: [system] Successfully activated service 'org.freedesktop.PackageKit'
Oct 28 00:46:53 notebook dbus[680]: [system] Successfully activated service 'org.freedesktop.PackageKit'
Oct 28 00:48:07 notebook kernel: [54414.492943] usb 1-4.4: USB disconnect, device number 24
Oct 28 00:48:08 notebook udevd[320]: specified group 'plugdev' unknown
Oct 28 00:48:08 notebook udisksd[1138]: Cleaning up mount point /run/media/olej/RFRemix-17-i686-Live-GNOME (device 8:17 no longer exist)
Oct 28 00:48:08 notebook logger: ====== REM : /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 ======
Oct 28 00:48:08 notebook logger: ====== REM : /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 /dev/bus/usb/001/024 ======
Здесь есть над чем подумать! ;-)
И то же самое как оно выглядит в новой системе журналирования journal (из комплекта systemd):

Код: Выделить всё

[root@notebook udev]# journalctl -n14 --no-tail
Logs begin at Sat, 27 Oct 2012 09:41:22 +0300, end at Sun, 28 Oct 2012 00:48:08 +0300.
Oct 28 00:45:52 notebook udevd[320]: specified group 'plugdev' unknown
Oct 28 00:45:52 notebook mtp-probe[11355]: checking bus 1, device 24: "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4"
Oct 28 00:45:52 notebook mtp-probe[11355]: bus: 1, device: 24 was not an MTP device
Oct 28 00:45:52 notebook logger[11357]: ====== ADD 1307:0163 /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 /dev/bus/usb/001/024 ======
Oct 28 00:45:52 notebook logger[11359]: ====== ADD : /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 ======
Oct 28 00:45:53 notebook udisksd[1138]: Mounted /dev/sdb1 at /run/media/olej/RFRemix-17-i686-Live-GNOME on behalf of uid 1000
Oct 28 00:46:53 notebook dbus-daemon[680]: dbus[680]: [system] Activating service name='org.freedesktop.PackageKit' (using servicehelper)
Oct 28 00:46:53 notebook dbus[680]: [system] Activating service name='org.freedesktop.PackageKit' (using servicehelper)
Oct 28 00:46:53 notebook dbus-daemon[680]: dbus[680]: [system] Successfully activated service 'org.freedesktop.PackageKit'
Oct 28 00:46:53 notebook dbus[680]: [system] Successfully activated service 'org.freedesktop.PackageKit'
Oct 28 00:48:08 notebook udevd[320]: specified group 'plugdev' unknown
Oct 28 00:48:08 notebook udisksd[1138]: Cleaning up mount point /run/media/olej/RFRemix-17-i686-Live-GNOME (device 8:17 no longer exist)
Oct 28 00:48:08 notebook logger[11442]: ====== REM : /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 ======
Oct 28 00:48:08 notebook logger[11444]: ====== REM : /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 /dev/bus/usb/001/024 ======
4. Очень интересный вопрос: почему уведомлений ADD - 2, и REM - 2?
Повторяю вывод (самое начало):

Код: Выделить всё

bash-4.2$ udevadm monitor --env
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[28414.391527] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb)
ACTION=add
BUSNUM=001
DEVNAME=/dev/bus/usb/001/009
DEVNUM=009
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4
DEVTYPE=usb_device
MAJOR=189
MINOR=8
PRODUCT=1307/163/100
SEQNUM=2407
SUBSYSTEM=usb
TYPE=0/0/0

KERNEL[28414.392459] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 (usb)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0
DEVTYPE=usb_interface
INTERFACE=8/6/80
MODALIAS=usb:v1307p0163d0100dc00dsc00dp00ic08isc06ip50
PRODUCT=1307/163/100
SEQNUM=2408
SUBSYSTEM=usb
TYPE=0/0/0

KERNEL[28414.392757] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host7 (scsi)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0/host7
DEVTYPE=scsi_host
SEQNUM=2409
SUBSYSTEM=scsi
Я показал только 3 первых дайтаграмы (сообщений) от ядра - только те в выводе команды, которые квалифицируются как KERNEL.
Только 2 первых из них имеют значение

Код: Выделить всё

SUBSYSTEM=usb
Оно же указано в правилах udev. Именно эти 2 сообщения (из гораздо большего числа) попали в лог. Остальные (с другими значениями SUBSYSTEM) следовали при дальнейшей раскрутке этого устройства как SCSI, блочного, его монтированию и т.д.

Из этого же листинга :

Код: Выделить всё

bash-4.2$ udevadm monitor --env
...
- берём значения параметров для составления правил udev, и они же передаются как параметры вызова наших собственных скриптов.

Вот и 1-я работающая схема асинхронных уведомлений процесса на hot-plug подключение-отключение устройств.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 29 окт 2012, 00:08

Olej писал(а): Вот так вот можно наблюдать как "посыпятся" сообщения через netlink:
Сделал тестовое приложение, которое получает непосредственно из netlink уведомления от ядра об изменениях в подсистеме /sys, т.е. подключении-отключении устройств. Это в точности те уведомления (дэйтаграмы сокета netlink), и приходят они в приложение одновременно, параллельно с udevd и udevadm.

Вот 2 последние дэйтаграмы уведомлений от ядра при подключении-отключении USB-флешки (естественно, 2 последних пакета - это относится к отключению):

Код: Выделить всё

bash-4.2$ ./mondev
..........................................................
remove@/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4
ACTION=remove
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4
SUBSYSTEM=usb
MAJOR=189
MINOR=33
DEVNAME=bus/usb/001/034
DEVTYPE=usb_device
PRODUCT=1307/163/100
TYPE=0/0/0
BUSNUM=001
DEVNUM=034
SEQNUM=3184
..........................................................
remove@/host32/target32:0:0
ACTION=remove
DEVPATH=/host32/target32:0:0
SUBSYSTEM=scsi
DEVTYPE=scsi_target
SEQNUM=3185
Это в точности совпадает с тем, как их же (пакеты уведомления) видит штатная утилита:

Код: Выделить всё

bash-4.2$ udevadm monitor --property --kernel
...
KERNEL[22846.212590] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb)
ACTION=remove
BUSNUM=001
DEVNAME=/dev/bus/usb/001/034
DEVNUM=034
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4
DEVTYPE=usb_device
MAJOR=189
MINOR=33
PRODUCT=1307/163/100
SEQNUM=3184
SUBSYSTEM=usb
TYPE=0/0/0

KERNEL[22846.263379] remove   /host32/target32:0:0 (scsi)
ACTION=remove
DEVPATH=/host32/target32:0:0
DEVTYPE=scsi_target
SEQNUM=3185
SUBSYSTEM=scsi
Пришлось изрядно повозиться ... перелопатить исходный код udevd из GIT-репозитария.
Сложность и неприятность составляет единственно то, что формат дэйтаграмм netlink нигде не описан. И, похоже, он разительно (произвольно?) отличается в зависимости от подсистемы, от которой мы хотим получать уведомления. Если это сетевая подсистема:

Код: Выделить всё

fd = socket( PF_NETLINK, SOCK_RAW, NETLINK_ROUTE )
то это формат некоторых таблиц с бинарными заголовками ... http://smokeman85.blogspot.com/2011/09/ ... linux.html :

Код: Выделить всё

/*
   Данные в буфере имеют следующий вид:
   |nlmsghdr|data|nlmsghdr|data|....|nlmsghdr|data|
   |-------------------size-----------------------|
*/
Но в уведомлениях /sys всё совершенно по-другому:

Код: Выделить всё

fd = socket( AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT ); 

Здесь это просто последовательность 0-терминейтед строк ... причём даже не оканчивающихся пустой строкой ("\0\0"), а заканчивающейся последней терминальной строкой вида "SEQNUM=<число>" (последовательный номер уведомления), так что растаскивать строки параметров получается как-то так:

Код: Выделить всё

      char *p = buf;
      while( 1 ) {
         printf( "%s\n", p );
         if( strstr( p, "SEQNUM=" ) == p ) break;
         p += ( strlen( p ) + 1 );
      };
Вложения
mondev.tgz
(3.62 КБ) 752 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 10 апр 2014, 14:02

Понадобилось ещё раз повозиться с udev, на этот раз не с железом, а с установкой драйверов (модулей):

- загружаю модуль (свой собственный):

Код: Выделить всё

bash-4.2$ sudo insmod fixdev.ko
[sudo] password for Olej:
bash-4.2$ lsmod | head -n2
Module                  Size  Used by
fixdev                 12630  0
bash-4.2$ dmesg | tail -n1 | grep ===
[21383.789733] =========== module installed 246:0 ==============
Такой модуль есть в примерах к тексту "Модули ядра ...", но это не так важно.
Модуль устанавливается (автоматом) на свободный major номер 246

- в это время для udev поступает сообщение:

Код: Выделить всё

bash-4.2$ udevadm monitor --property
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[21383.789383] add      /module/fixdev (module)
ACTION=add
DEVPATH=/module/fixdev
SEQNUM=2324
SUBSYSTEM=module

UDEV  [21383.790971] add      /module/fixdev (module)
ACTION=add
DEVPATH=/module/fixdev
SEQNUM=2324
SUBSYSTEM=module
USEC_INITIALIZED=383789737

... ...
- загрузка драйвера (никакого железа!) тут же отображается через реакцию sysfs :

Код: Выделить всё

bash-4.2$ cat /proc/devices | grep my_cdev_dev
246 my_cdev_dev
bash-4.2$ cat /sys/module/fixdev/parameters/major
246
Нужно:
- написать правила, fixdev.rules для того, чтобы при загрузке драйвера...
- создавалось имя устройства, делался:

Код: Выделить всё

# mknode -m0666 /dev/fixdev
- ну и, соответственно, убиралось при выгрузке модуля.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 26 фев 2016, 13:43

Olej писал(а): Нужно:
- написать правила, fixdev.rules для того, чтобы при загрузке драйвера...
По поводу правил udev - несколько хороших публикаций:

- Как писать правила для udev
by Daniel Drake (dsd)
Version 0.74
Перевод: Аркадий Иванов (arc@ikir.ru)
Вот другой перевод того же источника (Алексей Дмитриев), здесь на сайте размещённый.


- Управление аппаратными средствами в Linux с помощью udev
From: MooSE <webmaster@ylsoftware.com.>
Date: Sun, 5 Nov 2007 17:02:14 +0000 (UTC)
- Управление устройствами с помощью udev
2 февраля 2010 г.
Эта статья перевод 19-ой главы OpenSUSE Reference Guide, которое можно скачать в PDF-формате или просто посмотреть в формате html через браузер здесь.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 19 янв 2017, 11:43

Olej писал(а): По поводу правил udev - несколько хороших публикаций:
Ещё одна более-менее внятная публикация про написание правил udev: Udev и его применение для монтирования файловой системы.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: асинхронные уведомления и udev

Непрочитанное сообщение Olej » 02 июн 2017, 13:19

Olej писал(а):Демоны системы udev:

Код: Выделить всё

bash-4.2$ ps -AF | grep udev
root       320     1  0  1292  1980   1 09:41 ?        00:00:00 /usr/lib/udev/udevd
root       711   320  0  1291  1400   1 09:41 ?        00:00:00 /usr/lib/udev/udevd
root       712   320  0  1291  1396   0 09:41 ?        00:00:00 /usr/lib/udev/udevd
olej      2751  2727  0  1193   772   1 10:02 pts/2    00:00:00 grep udev
Мне не совсем понятно почему их должно работать в системе 3 ... , но оставим это на потом.
Через сколько-то-там лет (5?) и совсем в другой системе/дистрибутиве (обновляемся ;-) ):

Код: Выделить всё

[olej@dell SinCos]$ ps -AF | grep udev | grep ^root
root       570     1  0 11460  5564   3 май31 ?     00:00:01 /usr/lib/systemd/systemd-udevd

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 6 гостей