udev(8) is the latest development in the complicated history of device management in Linux. It has not been entirely uncontroversial. It was previously hated for its decision to change syntax. Its integration into systemd caused the eudev fork to happen, and the decision to remove firmware loading support made Linus grumble.
This article isn't about that though, this is about what udev(8) is, what it can do, and how you would use it.
udev(8) is for managing the contents of /dev
to handle permissions
of which users and groups may access devices under which names, and
providing an API for other services to use to recieve notification of
when devices change.
You tend not to need to interact with udev(8) directly unless you have obscure hardware that you need to categorise, or you need to perform actions when a device appears.
Granting permission to access devices
If the device has already been processed such that there's an entry in
/dev
, then you can use udevadm(8) and the steps in this ArchLinux
wiki page on writing udev rules to work out how to create a persistent
symlink.
To change the owner of the file, so you don't need to be root to use it,
you can add GROUP="GROUPNAME"
, subtituting the group name wanted, and
set file permission bits with MODE="0660"
to make that group able to
read or write to that device.
Performing actions when a device appears
Short, simple scripts
The simplest way to do this is to add RUN+="/path/to/your/script"
to your udev(8) rule, however this is only suitable for short-lived
scripts, as they will be killed if they are stil running after a timeout
period.
Starting a daemon per-device
If you need a longer-running service, then you should integrate it with a systemd unit, by defining the unit like:
cat >/etc/systemd/system/my-service@.service <<'EOF'
[Unit]
Description=My Service
[Service]
Type=simple
ExecStart=/path/to/your/script %I
EOF
And add ENV{SYSTEMD_WANTS}="my-service@%k.service"
to the udev rule.
This will run /path/to/your/script
and pass it the path to the device
that has just appeared.
Handling device events from a currently-running daemon
Sometimes it is not appropriate to have a model where there is an instance of your service running for every device that is added. In this case, it is more appropriate to have your service listen for udev events and handle the devices when they appear itself.
The details on how to do this vary with the programming language bindings, but the general flow is:
- Initialize the udev library context
- Create a udev monitor
- Configure the monitor to filter it to the class of devices you care about
- Add the monitor to an event loop
- Wait for udev to have a matching entry for you
- Read the device entry out of udev and process the event
Depending on your programming language of choice, you may want a guide for how to listen for devices with libudev, or pyudev.