Uevent отправляется из ядра в пользовательское пространство (udev)

Я знал, что udev играет в системе linux, и он получает uevents, отправленные из ядра через сокет netlink.

Однако мои вопросы:

  • Как ядро ​​отправляет событие? Это должно быть что-то, вызванное добавлением/удалением устройства, а затем отправляет события в udev. Как это делает ядро? (Есть ли какой-нибудь пример кода, который я могу найти?)

  • udev получает эти uevents только через сокет netlink. Это единственный способ, которым udev это делает. Правильно ли это?

  • Когда uevent отправляется из ядра, я знал, что он может транслировать. Однако, может ли он сделать одноадресную рассылку?

Спасибо за любую обратную связь.

Ответ 1

  1. Он отправляет сообщение netlink с именем uevent. uevent - это просто строка некоторого специального формата, который отправляется через сокет netlink. Пример:

    "[email protected]/class/input/input9/mouse2\0    // message
    ACTION=add\0                         // action type
    DEVPATH=/class/input/input9/mouse2\0 // path in /sys
    SUBSYSTEM=input\0                    // subsystem (class)
    SEQNUM=1064\0                        // sequence number
    PHYSDEVPATH=/devices/pci0000:00/0000:00:1d.1/usb2/2­2/2­2:1.0\0  // device path in /sys
    PHYSDEVBUS=usb\0       // bus
    PHYSDEVDRIVER=usbhid\0 // driver
    MAJOR=13\0             // major number
    MINOR=34\0",           // minor number
    

    Функция ядра, которая фактически отправляет uevent, это kobject_uevent_env и она kobject_uevent который вызывается во многих местах.

  2. Да, udev работает, получая uevents из сокета netlink. Но есть опция - ядро может вызвать помощник usermode. В этом случае ядро запускает один процесс на событие hotplug, предоставляя переменные среды каждому новому процессу, описывающему это событие hotplug. Если вы посмотрите на kobject_uevent_env вы увидите, что сообщение netlink на самом деле #ifdef 'ed, а действие по умолчанию - вызов этого помощника usermode

  3. Теоретически сообщения netlink могут быть широковещательными, многоадресными и одноадресными, но ядро отправляет широковещательное сообщение с netlink_broadcast_filtered вызова netlink_broadcast_filtered. В любом случае это сообщение отправляется в сокет семейства NETLINK_KOBJECT_UEVENT. Вы можете видеть создание сокета netlink в uevent_net_init.

  4. Отвечая на ваш вопрос. Вы не увидите никакой функции send в ядре. send - это системный вызов - это интерфейс, предоставляемый ядром для пользовательского пространства, но сам ядро не использует никаких системных вызовов. Существует длинная цепочка вызовов функций (в net/netlink/af_netlink.c и net/core/dev.c) от kobject_uevent_env до окончательной отправки, которая не содержит никакого send ядра, отправляющего skb (буфер сокета) - это что-то вроде размещение буфера в очереди, а затем вызов планировщика для доставки этого буфера и уведомление пользователя, ожидающего в syscall recv

Ресурсы:

  1. Библиотека /kobject_uevent.c
  2. https://www.kernel.org/doc/pending/hotplug.txt - есть программа пользовательского пространства, которая прослушивает uevents и печатает ее.
  3. https://bootlin.com/doc/legacy/udev/udev.pdf