Uevent Sent from Kernel to User Space (Udev)

uevent sent from kernel to user space (udev)


  1. It sends netlink message called uevent. uevent is just string of some special format that is sent via netlink socket. Example:

     "add@/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

    Kernel function that actually sends uevent is kobject_uevent_env and it's wrapper kobject_uevent that is called in many places.

  2. Yes, udev works by receiving uevents from netlink socket. But there is an option - kernel can call usermode helper. In this case kernel spawns one process per hotplug event, supplying environment variables to each new process describing that particular hotplug event. If you look at kobject_uevent_env you'll see that netlink message is actually #ifdef'ed and default action is to call that usermode helper

  3. In theory netlink messages can be broadcast, multicast and unicast, but kernel sends broadcast message with netlink_broadcast_filtered call. Anyway that message goes to socket of NETLINK_KOBJECT_UEVENT family. You can see netlink socket creation in uevent_net_init.

  4. Answering your comment question. You will not see any send function in kernel. send is a system call - it's interface that kernel provides to userspace, but kernel itself does not use any of syscalls. There is a long chain of function calls (in net/netlink/af_netlink.c and net/core/dev.c) from kobject_uevent_env to final sending that doesn't contain any send - in kernel sending skb (socket buffer) is something like placing buffer in queue and then calling scheduler to deliver that buffer and notify userspace that is waiting on syscall recv

Resources:

  1. lib/kobject_uevent.c
  2. https://www.kernel.org/doc/pending/hotplug.txt - has userspace program that listens for uevents and prints it.
  3. https://bootlin.com/doc/legacy/udev/udev.pdf

how uevents get triggered in kernel

I can't agree with you about polling. uevent is event-based, so there is no polling.

Triggering uevent happened in many cases and I would rather start with figuring out what uevent types are exist?

Little searching and here you go - in include/linux/kobject.h

enum kobject_action {
KOBJ_ADD,
KOBJ_REMOVE,
KOBJ_CHANGE,
KOBJ_MOVE,
KOBJ_ONLINE,
KOBJ_OFFLINE,
KOBJ_MAX
};

So it's

  • Add event
  • Remove event
  • Change event
  • Move event
  • Online event
  • Offline event

KOBJ_MAX is special and marks and of enum.

There are 2 functions that actually sends uevent - kobject_uevent and kobject_uevent_env. These functions are called with on of the actions listed above.

Finally, to answer your questions. There are no predefined cases that will trigger uevent. If you search for calls of kobject_uevent and kobject_uevent_env you will see that it's happens in various callbacks in different unrelated kernel subsystems.

uevent is kernel facility to unify notifications from various unrelated drivers. So I think there are no well known list of things that will trigger uevent.

How to register for an uevent from a user application in Linux?

It is possible and there is a great reference here. In the reference they use a change rule for a similar application:

# Rule for when switching to battery
ACTION=="change", SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="0", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/USERNAME/.Xauthority" RUN+="/usr/bin/su USERNAME_TO_RUN_SCRIPT_AS -c /usr/local/bin/brightness_notification.sh"

The ACTION=="change" registers a rule for a change event. The SUBSYSTEM and ATTR parameters specify the rule to only apply to a certain device or devices (you can get these for your device from udevadm). The RUN parameter is how you run a userspace executable when the event is seen. In the case below they also use the ENV parameter to pass a environment variable to the executable and they also use the su command in RUN to run the executable as another user, but this is probably not necessary for most applications.

Listen for harware change events from the linux kernel or udev

You can use libudev or the more convenient, glib based gudev to monitor udev events in C.

udevadm vs linux hotplug


  1. Yes, you're right. udevadm is to manage udevd.
  2. This is where you're really confused. Let me clarify this. udev is userspace device manager. udev is responsible for your devices to appear in /dev directory. It's also responsible for hotplug functionality. To make things done udev works by receiving messages from kernel. Kernel sends messages via netlink socket. Netlink is just IPC facility implemented as separate socket family specifically for kernel to userspace interaction. So kernel sends messages of special format (uevent) over netlink socket. On the other site (in userspace) there must be someone who is listening for this messages and that's what udev does. Main part of udev is udev daemon - udevd. That daemon listens for that messages and creates special device files under /dev path and provide to you (linux user) interface to manage devices and hotplug (udev rules).

I've answered related question - check it here.

Extra answers:

  1. From udevadm manpage:

    udevadm expects a command and command specific options. It controls
    the runtime behavior of systemd-udevd, requests kernel events, manages
    the event queue, and provides simple debugging mechanisms.

    So it's just a managing tool though it can requests kernel event on admin command.

  2. (I might not understand you question correctly). You can write your own daemon to listen for uevents. That's what gentoo's mdev does.

  3. Netlink allows you to provide multiple listeners for netlink messages. But it depends on a way that kernel socket sends message (unicast, multicast, broadcast) and netlink family. Netlink itself is a collection of families, so it may depends on what netlink you are using. For example, NETLINK_GENERIC family allows you to bind multiple userspace sockets for messages and you will receive that messages. I think the best way to answer this question is to write some simple listening code (probably with some help of libudev)

udevd and initcall dependency

Firstly udev is just one mechanism for creating device nodes. Your code should be creating a device in the kernel device model, and then something will create a device node in /dev for your device. On an embedded system that may just be a simple shell script.

As far as timing goes, if your device is created early in boot then udev and the kernel will handle replaying the creation event once udev is up and running. This happens via udev scanning /sys and writing "add" to the uevent file of each device. That tells the kernel to send the creation event, which udev receives via netlink (or it could use uevent_helper).

Also even without udev your device will appear somewhere in /sys where you can query its major and minor number and create the device node manually.



Related Topics



Leave a reply



Submit