Generating and Utilizing Kernel UEVENTS


Learn about how to interact with the Linux kernel using UEvents in your userspace applications! Guides on available tools to help your development.

Table of Contents

  1. Overview
  2. Monitoring Uevents
  3. Decoding Kernel Uevents
  4. Utilizing UEVENTs
  5. Testing UDEV Rules

Overview

UEvents are generated using kobject APIs, such as kobject_uevent() from within kernel drivers. They can be used to communicate changes to a particular kernel device to userspace. Userspace can utilize these events to further query the device’s sysfs files for any new changes.

For example, the USB bus generates a kernel uevent whenever there is an addition or removal of a USB device. Userspace can use this to configure the USB device to the desired behavior, such as enabling USB auto-suspend. (disabled for every USB class other than hubs)

Having the ability in userspace to wait for asynchronous events is useful so cycles can go to handling other operations, and interrupted only when a change occurs. This post will cover topics such as:

  • Tooling to monitor kernel uevents
  • Uevent formatting
  • Utilizing UEVENTS
  • Testing UEVENTS

Monitoring Uevents

There are several tools that are available for helping with monitoring and testing kernel uevents. For Yocto based distributions, at least, there is the udevadm application.

sh-5.0# udevadm monitor
monitor will print the received events for: 
UDEV - the event which udev sends out after rule processing 
KERNEL - the kernel uevent 

KERNEL[9298.812693] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9298.818565] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9298.823931] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9298.825485] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9298.832052] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9298.835133] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9298.836787] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9298.842368] change /devices/virtual/misc/usb_haxx (misc) UDEV [9298.961581] change /devices/virtual/misc/usb_haxx (misc) UDEV [9304.731556] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9305.662434] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9305.664833] change /devices/virtual/misc/usb_haxx (misc) KERNEL[9305.667829] change /devices/virtual/misc/usb_haxx (misc)

Useful Command Arguments:

  • -p : prints properties associated with the uevent
  • -s : filters events based on subsystem
    • Valid Values:
      • usb, hid, etc…

Monitoring for uevents is helpful so that users can properly reference the correct device path and kobject event to trigger certain actions in the application. If your distribution does not include udevadm, busybox has an uevent applet that can be enabled and achieves a similar output.

sh-5.0# busybox uevent 
add@/devices/pci0000:00/0000:00:0c.0/usb1/1-2 ACTION=add DEVPATH=/devices/pci0000:00/0000:00:0c.0/usb1/1-2 SUBSYSTEM=usb MAJOR=189 MINOR=12 DEVNAME=bus/usb/001/013 DEVTYPE=usb_device PRODUCT=1532/228/200 TYPE=0/0/0 BUSNUM=001 DEVNUM=013 SEQNUM=3624

Decoding Kernel UEvents

Normally, an application or userspace entity that listens for kernel uevents, focuses on the following information:

  • Device Path – device which generated the uevent
    • /devices/virtual/misc/usb_haxx
    • /devices/pci0000:00/0000:00:0c.0/usb1/1-2
  • UEvent Type – type of UEvent
    • change
    • add

Device Path

This is used to help filter kernel uevents. All UEvents are generated on the NETLINK_KOBJECT_UEVENT socket. Hence, an application may only be interested in changes occurring for a specific device or subsystem.

UEvent Type

Defined by

enum kobject_action { 
KOBJ_ADD, KOBJ_REMOVE, KOBJ_CHANGE, KOBJ_MOVE, KOBJ_ONLINE, KOBJ_OFFLINE, KOBJ_BIND, KOBJ_UNBIND,
};
Kernel EnumUEvent Action
KOBJ_ADDadd
KOBJ_REMOVEremove
KOBJ_CHANGEchange
KOBJ_MOVEmove
KOBJ_ONLINEonline
KOBJ_OFFLINEoffline
KOBJ_BINDbind
KOBJ_UNBINDunbind

Utilizing UEVENTS

The udev daemon has support for filtering and triggering commands based on the UEvent’s device path and action type. Each subsystem may define their own set of UEvent properties that can used within the udev rules created. To help find the types of properties that are available for a particular device, the following command can be used:

udevadm info -q property -p /sys/devices/pci0000:00/0000:00:0c.0/usb1/1-2 

DEVPATH=/devices/pci0000:00/0000:00:0c.0/usb1/1-2 
DEVNAME=/dev/bus/usb/001/017 
DEVTYPE=usb_device 
DRIVER=usb PRODUCT=bda/48a8/1 
TYPE=0/0/0 
BUSNUM=001 
DEVNUM=017 
MAJOR=189 
MINOR=16 
SUBSYSTEM=usb 
USEC_INITIALIZED=76909655318 
ID_VENDOR=Generic 
ID_VENDOR_ENC=Generic 
ID_VENDOR_ID=0bda 
ID_MODEL=USB_Audio 
ID_MODEL_ENC=USB\x20Audio 
ID_MODEL_ID=48a8 
ID_REVISION=0001 
ID_SERIAL=Generic_USB_Audio 
ID_BUS=usb 
ID_USB_INTERFACES=:010100:010200:030000: 
ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp. 
ID_PATH=pci-0000:00:0c.0-usb-0:2 
ID_PATH_TAG=pci-0000_00_0c_0-usb-0_2 
ID_FOR_SEAT=usb-pci-0000_00_0c_0-usb-0_2 
TAGS=:seat: CURRENT_TAGS=:seat:

Command Arguments:

  • -q : signifies the category of information interested in
    • Valid Values:
    • name, symlink, path, property, all
  • -p : path to the device
    • Valid Values:
      • path to the device of interest

These are all defined within systemd. In the example above, these are the properties that belong with the USB subsystem, and users can write rules to match these properties. A simple rule can look like the following:

# Filter based on devpath and uevent action 
ACTION=="change", DEVPATH=="/devices/virtual/misc/usb_haxx", RUN+="/etc/udev/scripts/uevent.sh"

The rule matches any uevent that has a “change” action on the /devices/virtual/misc/usb_haxx device. If found, the rule will run the uevent.sh script, which will query for further device changes, or will issue some other operation.

Testing UDEV Rules

The udevadm application has some very useful tools built in, and one of the possible arguments is the “trigger” command. The trigger option will allow users to test their udev rules that they’ve written for a particular device.

# Triggers an "add" action for the usb1 device 
sudo udevadm trigger -c add -y usb1

If monitoring from another terminal/console, after running the trigger command, the monitor output will have the following

UDEV [82838.795432] add /devices/pci0000:00/0000:00:0c.0/usb1 (usb) 

ACTION=add 
DEVPATH=/devices/pci0000:00/0000:00:0c.0/usb1 
SUBSYSTEM=usb 
SYNTH_UUID=0 
DEVNAME=/dev/bus/usb/001/001 
DEVTYPE=usb_device 
DRIVER=usb 
PRODUCT=1d6b/2/515 
TYPE=9/0/1 
BUSNUM=001 
DEVNUM=001 
SEQNUM=4346 
USEC_INITIALIZED=3523846 
ID_VENDOR=Linux_5.15.0-56-generic_xhci-hcd 
ID_VENDOR_ENC=Linux\x205.15.0-56-generic\x20xhci-hcd 
ID_VENDOR_ID=1d6b 
ID_MODEL=xHCI_Host_Controller 
ID_MODEL_ENC=xHCI\x20Host\x20Controller 
ID_MODEL_ID=0002 ID_REVISION=0515 
ID_SERIAL=Linux_5.15.0-56-generic_xhci-hcd_xHCI_Host_Controller_0000:00:0c.0 
ID_SERIAL_SHORT=0000:00:0c.0 ID_BUS=usb 
ID_USB_INTERFACES=:090000: 
ID_VENDOR_FROM_DATABASE=Linux Foundation 
ID_AUTOSUSPEND=1 
ID_MODEL_FROM_DATABASE=2.0 root hub 
ID_PATH=pci-0000:00:0c.0 
ID_PATH_TAG=pci-0000_00_0c_0 
ID_FOR_SEAT=usb-pci-0000_00_0c_0 
MAJOR=189 
MINOR=0 
TAGS=:seat: 
CURRENT_TAGS=:seat:

Command Arguments:

  • -c : uevent action
    • Valid Values:
      • add, change, bind, etc…
  • -y : device path substring match
    • Valid Values:
      • usb1
      • Will match devices with “usb1” included in the device path.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *