Beginners Guide to Udev in Linux

Udev is the device manager for the Linux kernel. Udev dynamically creates or removes device node files at boot time in the /dev directory for all types of devices. Udev is now part of systemd as you can see by viewing the “udev” file names included with the systemd RPM package.

# rpm -ql systemd | grep udev
/etc/udev
/etc/udev/hwdb.bin
/etc/udev/rules.d
/etc/udev/udev.conf
/usr/bin/udevadm
...

 

The Udev daemon, systemd-udevd, receives device uevents directly from the kernel whenever a device is added or removed from the system. For every event, systemd-udevd executes matching instructions specified in Udev rules.

 

Device file names can change when disks are removed from the system due to failure. For example, devices are named /dev/sda, /dev/sdb, and /dev/sdc at boot time. But on the next reboot, /dev/sdb fails and what was previously /dev/sdc is named /dev/sdb. Any configuration references to /dev/sdb now contain content originally referenced by /dev/sdc.

 

The solution to avoid this type of situation is to guarantee consistent names for devices through reboots. You can configure Udev to create persistent names and use these names in the file system mount table, /etc/fstab, or as an argument to the mount command.

 

Udev Rule Files and Directories

 

Udev rules determine how to identify devices and how to assign a name that is persistent through reboots or disk changes. When Udev receives a device event, it matches the configured rules against the device attributes in sysfs to identify the device. Rules can also specify additional programs to run as part of device event handling.

 

Udev rules files are located in the following directories:

  • /lib/udev/rules.d/ – The default rules directory
  • /etc/udev/rules.d/ – The custom rules directory. These rules take precedence.

 

Rules files need to have unique names. Files in the custom rules directory override files of the same name in the default rules directory. Rules files are sorted and processed in lexical order. The following is a partial listing of rules files from the default and custom rules directories:

# ls -l /lib/udev/rules.d/
total 348
-r--r--r--. 1 root root  7266 Aug  5  2017 10-dm.rules
-r--r--r--. 1 root root  2454 Aug  5  2017 11-dm-lvm.rules
-rw-r--r--. 1 root root  2865 Jan 25 16:05 11-dm-mpath.rules
-r--r--r--. 1 root root  1499 Aug  5  2017 13-dm-disk.rules
-rw-r--r--. 1 root root   553 Aug  6  2017 39-usbmuxd.rules
-rw-r--r--. 1 root root  1622 Mar  7 13:27 40-redhat.rules
...

 

# ls -l /etc/udev/rules.d/
total 8
-rw-r--r--. 1 root root 709 Aug  4  2017 70-persistent-ipoib.rules
-rw-r--r--. 1 root root  96 Apr 21 05:09 70-persistent-net.rules
lrwxrwxrwx. 1 root root   9 Sep 29  2014 80-net-name-slot.rules -> /dev/null

 

Sample Udev Rules

 

Below example contains selected entries from the /lib/udev/rules.d/50-udev-default.rules file. This rules file contains over 60 entries.

 

# cat /lib/udev/rules.d/50-udev-default.rules 
# do not edit this file, it will be overwritten on update

SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}"

# select "system RTC" or just use the first one
SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc"
SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"

SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}"

ACTION!="add", GOTO="default_permissions_end"

SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666"
SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666"
SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620"
SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620"
SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620"
....

 

The selected entries assist in describing the syntax of the rules files.

 

1. Comments begin with a # sign.

 

2. Each non-commented line in a rules file consists of a list of one or more key-value pairs separated by a comma. There are two types of keys:

  • Match keys
  • Assignment keys

 

3. If all match keys match their respective value, the rule gets applied and the assignment keys are assigned the specified value. Each key has a distinct operation, depending on the operator. Valid operators are:

 

  • == : Compare for equality
  • != : Compare for inequality
  • = : Assign a value to a key
  • += : Add the value to the current values for the key
  • := : Assign the final value to the key. Disallow any later changes by any later rules.

 

4. Shell-style pattern matching (*, ?, []) is also supported in Udev rules.

 

Match Keys

 

The following key names are used to match against device properties. Some of the keys also match against properties of the parent devices in sysfs, and not just the device that has generated the event. If multiple keys are specified in a single rule, all these keys must match.

 

  • ACTION: Match the name of the event action.
  • DEVPATH: Match the devpath of the event device.
  • KERNEL: Match the name of the event device.
  • NAME: Match the name of a network interface. It can be used if the NAME key was set in one of the preceding rules.
  • SYMLINK: Match the name of the symlink targeting the node. It can be used if a SYMLINK key was set in one of the preceding rules. There can be multiple symlinks but only one needs to match.
  • SUBSYSTEM: Match the subsystem of the event device.
  • TEST{octal mode mask}: Test the existence of a file. You can specify the octal mode mask.

 

Other match keys include DRIVER, ATTR{filename}, KERNELS, SUBSYSTEMS, DRIVERS, ATTRS{filename}, TAGS, ENV{key}, TAG, PROGRAM, and RESULT.

 

Assignment Keys

The following keys can have values assigned to them:

  • NAME – The name to use for a network interface. The name of a device node cannot be changed by Udev, only additional symlinks can be created.
  • SYMLINK – The name of the symlink targeting the node
  • OWNER, GROUP, MODE – The permissions for the device node
  • OPTIONS – Rule and device options. The ignore_remove option used in the example means “Do not remove the device node when the device goes away.”

Other assignment keys include ATTR{key}, ENV{key}, TAG, RUN{type}, LABEL, GOTO, IMPORT{type}, WAIT_FOR, and OPTIONS.

 

String Substitutions

 

The NAME, SYMLINK, PROGRAM, OWNER, GROUP, MODE, and RUN keys support many printf- like string substitutions. The substitutions used in the example are:

  • %M – The kernel major number for the device
  • %m – The kernel minor number for the device

 

Additional string substitutions are supported. Refer to the udev man page for all supported substitutions and details on additional match keys, additional assignment keys, and additional rule and device options.

 

udevadm Utility

 

The udevadm utility is a userspace management tool for Udev. Among other functions, you can use udevadm to query sysfs and obtain device attributes to help in creating Udev rules that match a device. To display udevadm usage:

# udevadm --help
udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]

Send control commands or test the device manager.

Commands:
  info          Query sysfs or the udev database
  trigger       Request events from the kernel
  settle        Wait for pending udev events
  control       Control the udev daemon
  monitor       Listen to kernel and udev events
  test          Test an event run
  test-builtin  Test a built-in command

 

You can also obtain usage for each of the udevadm commands. For example, to get help on using the info command:

# udevadm info --help
udevadm info [OPTIONS] [DEVPATH|FILE]

Query sysfs or the udev database.

  -h --help                   Print this message
     --version                Print version of the program
  -q --query=TYPE             Query device information:
       name                     Name of device node
       symlink                  Pointing to node
       path                     sysfs device path
       property                 The device properties
       all                      All values
  -p --path=SYSPATH           sysfs device path used for query or attribute walk
  -n --name=NAME              Node or symlink name used for query or attribute walk
  -r --root                   Prepend dev directory to path names
  -a --attribute-walk         Print all key matches walking along the chain
                              of parent devices
  -d --device-id-of-file=FILE Print major:minor of device containing this file
  -x --export                 Export key/value pairs
  -P --export-prefix          Export the key name with a prefix
  -e --export-db              Export the content of the udev database
  -c --cleanup-db             Clean up the udev database

 

Example of udevadm utility

 

Some examples follow. To query the Udev database for the device path of /dev/xvdd:  

# udevadm info --query=path --name=/dev/xvdd 
/devices/vbd-5696/block/xvdd

 

To query the Udev database for all device information for /dev/xvda:

# udevadm info --query=all --name=/dev/xvda
P: /devices/vbd-768/block/xvda
N: xvda
E: DEVNAME=/dev/xvda
E: DEVPATH=/devices/vbd-768/block/xvda
E: DEVTYPE=disk
E: DM_MULTIPATH_TIMESTAMP=1524287355
E: ID_PART_TABLE_TYPE=dos
E: MAJOR=202
E: MINOR=0
E: MPATH_SBIN_PATH=/sbin
E: SUBSYSTEM=block
E: TAGS=:systemd:
E: USEC_INITIALIZED=476119

 

Enter the following to print all sysfs properties of /dev/xvda. These properties can be used in Udev rules to match the device. It prints all devices along the chain, up to the root of sysfs.

# udevadm info --attribute-walk --name=/dev/xvda

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/vbd-768/block/xvda':
    KERNEL=="xvda"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{ro}=="0"
    ATTR{size}=="41943040"
    ATTR{stat}=="   16775        4   686095    36372     2953      313   203104    42044        0    19603    78392"
    ATTR{range}=="16"
    ATTR{discard_alignment}=="0"
    ATTR{ext_range}=="16"
    ATTR{alignment_offset}=="0"
    ATTR{badblocks}==""
    ATTR{inflight}=="       0        0"
    ATTR{removable}=="0"
    ATTR{capability}=="10"

  looking at parent device '/devices/vbd-768':
    KERNELS=="vbd-768"
    SUBSYSTEMS=="xen"
    DRIVERS=="vbd"
    ATTRS{devtype}=="vbd"
    ATTRS{nodename}=="device/vbd/768"

 

Creating a Symbolic Link to a Device Node

 

The order in which rules are evaluated is important. When creating your own rules, you want these evaluated before the defaults. Because rules are processed in lexical order, create a rules file with a file name such as /etc/udev/rules.d/10-local.rules for it to be processed first.

 

The following rule creates the /dev/my_disk symbolic link to the /dev/xvdd device node. You can create a Udev rule to change the name of a network interface but the name of a device node cannot be changed by Udev. Only additional symlinks can be created for device nodes.

 

KERNEL=="xvdd", SUBSYSTEM=="block", SYMLINK="my_disk"

 

Run udevadm trigger to process the rules files:

# udevadm trigger

 

The symlink now exists.

# ls –l /dev/my*
lrwxrwxrwx. ... /dev/my_disk -> xvdd

 

Remove the 10-local.rules file and run udevadm trigger to remove the symlink.

 

Was this answer helpful? 0 Users Found This Useful (0 Votes)