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 первых из них имеют значение
Оно же указано в правилах udev. Именно эти 2 сообщения (из гораздо большего числа) попали в лог. Остальные (с другими значениями SUBSYSTEM) следовали при дальнейшей раскрутке этого устройства как SCSI, блочного, его монтированию и т.д.
Из этого же листинга :
- берём значения параметров для составления правил udev, и они же передаются как параметры вызова наших собственных скриптов.
Вот и 1-я
работающая схема асинхронных уведомлений процесса на hot-plug подключение-отключение устройств.