Udevadm Vs Linux Hotplug

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)

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 to create a callback for monitor plugged on an intel graphics?

As a crude solution, you may be able to poll on sysfs. On my laptop I have:

$ cat /sys/class/drm/card0-LVDS-1/status
connected

$ cat /sys/class/drm/card0-VGA-1/status
disconnected

I'm guessing this requires kernel DRM and possibly KMS.

To see if you can trigger something automatically, you could run udevadm monitor --property, and watch while you are (dis-)connecting the monitor to see if events are reported.

With my radeon, I get an event the first time I connect a VGA monitor, but no events on subsequent disconnects and reconnects. The event should look something like (using yours as an example):

KERNEL[1303765357.560848] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV_LOG=0
ACTION=change
DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0
SUBSYSTEM=drm
HOTPLUG=1
DEVNAME=dri/card0
DEVTYPE=drm_minor
SEQNUM=2943
MAJOR=226
MINOR=0

Unfortunately there's not a lot to match against, but as long as there's only one video card in the picture that's not too important. Find where udev gets rules from on your system (probably /etc/udev/rules.d/), and create a 99-monitor-hotplug.rules file with:

ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/root/hotplug.sh"

udev will then run hotplug.sh when a display is connected. As a test, I put the following in /root/hotplug.sh (don't forget to make this script executable):

#!/bin/sh

for output in DVI-I-1 LVDS-1 VGA-1; do
echo $output >> /root/hotplug.log
cat /sys/class/drm/card0-$output/status >> /root/hotplug.log
done

With that, I got an entry in hotplug.log after I connected an external display. Even filtering for ACTION=="change", I still got some events on boot, so you may want to take that into account somehow in your script.

libudev how to use poll with the file descriptor

The program doesn't actually stop; it continues running, but std::cout gets messed up when you try to print a NULL string (not all events have all properties). A fix is to make the three prints (devnode, subsystem, devtype) conditional.



Related Topics



Leave a reply



Submit