uevent sent from kernel to user space (udev)
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/22/22:1.0\0 // device path in /sys
PHYSDEVBUS=usb\0 // bus
PHYSDEVDRIVER=usbhid\0 // driver
MAJOR=13\0 // major number
MINOR=34\0", // minor numberKernel function that actually sends uevent is
kobject_uevent_env
and it's wrapperkobject_uevent
that is called in many places.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 helperIn 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 ofNETLINK_KOBJECT_UEVENT
family. You can see netlink socket creation inuevent_net_init
.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) fromkobject_uevent_env
to final sending that doesn't contain anysend
- 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 syscallrecv
Resources:
- lib/kobject_uevent.c
- https://www.kernel.org/doc/pending/hotplug.txt - has userspace program that listens for uevents and prints it.
- 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
- Yes, you're right.
udevadm
is to manageudevd
. - 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 ofudev
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:
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.
(I might not understand you question correctly). You can write your own daemon to listen for uevents. That's what gentoo's mdev does.
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
How to Run a Windows Executable from Wsl (Ubuntu) Bash
Maximum Number of Concurrent Connections on a Single Port (Socket) of Server
Linux Command: How to 'Find' Only Text Files
How to Specify More Spaces for the Delimiter Using Cut
Send Mail from Linux Terminal in One Line
What Do These Kernel Panic Errors Mean
Linux Time Command Microseconds or Better Accuracy
Joining Multiple Fields in Text Files on Unix
How to Determine If a Detached Pthread Is Alive
Search and Replace with Sed When Dots and Underscores Are Present
How to Set Rpath and Runpath with Gcc/Ld
Install Mono and Monodevelop on Centos 5.X/6.X
Why Doesn't "Total" from Ls -L Add Up to Total File Sizes Listed
Are There Standards for Linux Command Line Switches and Arguments
Linking 32-Bit Library to 64-Bit Program
Why Is Rcx Not Used for Passing Parameters to System Calls, Being Replaced with R10
What Is the Correct Way to Start a Mongod Service on Linux/Os X
How to Check If a Program Is Run in Bash on Ubuntu on Windows and Not Just Plain Ubuntu