Chapter 15. Dynamic Device Nodes with udev
Table of Contents
Abstract
Linux kernel 2.6 introduces a new user space solution for a dynamic device directory /dev with consistent device designations: udev. The previous implementation of /dev with devfs no longer works and has been replaced by udev.
Traditionally, device nodes were stored in the /dev directory on Linux systems. There was a node for every possible type of device, regardless of whether it actually existed in the system. The result was that this directory took up a lot of space. The command devfs has brought a significant improvement, because now only devices that really exist are given a device node in /dev.
udev introduces a new way of creating device nodes. It compares the information made available by sysfs with data provided by the user in the form of rules. sysfs is a new file system in kernel 2.6. It provides basic information about devices connected to the system. sysfs is mounted under /sys.
It is not absolutely necessary for the user to create rules. If a device is connected, the appropriate device node is created. However, the rules introduce the possibility of changing the names for the nodes. This offers the convenience of replacing a cryptic device name with a name that is easy to remember and also of having consistent device names where two devices of the same type have been connected.
Unless otherwise specified, two printers are given the designations /dev/lp0 and /dev/lp1. Which device is given which device node depends on the order in which they are switched on. Another example is external mass storage devices, such as USB hard disks. The udev command allows exact device paths to be entered in /etc/fstab.
15.1. Creating Rules
Before udev creates device nodes under /dev, it reads the file /etc/udev/udev.rules. The first rule that fits a device is used, even if other rules would also apply. Comments are introduced with a hash sign (#). Rules take the following form:
key, [key,...] NAME [, SYMLINK]
At least one key must be specified, as rules are assigned to devices on the basis of these keys. It is also essential to specify a name, as the device node that is created in /dev bears this name. The optional symlink parameter allows nodes to be created in other places. A rule for a printer could thus take the following form:
BUS="usb", SYSFS{serial}="12345", NAME="lp_hp", SYMLINK="printers/hp"
In this example, there are two keys, BUS and SYSFS{serial}. udev compares the serial number to the serial number of the device that is connected to the USB bus. To assign the name lp_hp to the device in the /dev directory, all the keys must agree. In addition, a symbolic /dev/printers/hp, which refers to the device node, is created. During this operation, the printers directory is automatically created. Print jobs can then be sent to /dev/printers/hp or /dev/lp_hp.
15.2. Automization with NAME and SYMLINK
The parameters NAME and SYMLINK allow the use of operators for automatic assignments. These operators refer to kernel data on the corresponding device. A simple example illustrates the procedure:
BUS="usb", SYSFS{vendor}="abc", SYSFS{model}="xyz", NAME="camera%n"
The operator %n in the name is replaced by the number of the camera device: for example, camera0, camera1. Another useful operator is %k, which is replaced by the standard device name of the kernel, for example, hda1. Find a list of all the operators in the man page for udev.
15.3. Regular Expressions in Keys
Regular expressions, such as wild cards, can be used in the shell. For example, the character * can be used as a placeholder for any characters or ? can be used for precisely one character.
KERNEL="ts*", NAME="input/%k"
This rule assigns the standard kernel name in the standard directory to a device whose designation begins with the letters "ts". Detailed information about the use of regular expressions in udev rules can be found in the man page man udev.
15.4. Key Selection
It is essential to choose a good key for every functioning udev rule. Here are some examples of standard keys:
-
BUS
-
device bus type
KERNEL
-
device name the kernel uses
ID
-
device number on the bus (for example, PCI bus ID)
PLACE
-
physical point where the device is connected (for example, on USB)
The keys ID and PLACE can be useful, but usually the keys BUS, KERNEL, and SYSFS{...} are used. The udev configuration also provides keys that call external scripts and evaluate their results. Further details about this can be found in man udev.
The file system sysfs stores small files with hardware information in a directory tree. Each file generally is only given one item of information, such as the device name, the vendor, or the serial number. Each of these files can be used as the value of a key. To use several SYSFS keys in one rule, however, you can only use files in the same directory.
udevinfo can be a useful tool here. You just have to find one subdirectory of /sys that refers to the relevant device and is given a file dev. These directories are all located under /sys/block or/sys/class.
If a device node already exists for the device, udevinfo can again reduce the amount of work you have to do. The command udevinfo -q path -n /dev/sda outputs /block/sda. This means that the directory you are looking for is /sys/block/sda. Now call udevinfo with the following command: udevinfo -a -p /sys/block/sda. The two commands can also be combined, for example: udevinfo -a -p `udevinfo -q path -n /dev/sda`. The following is an extract from the output:
BUS="scsi" ID="0:0:0:0" SYSFS{detach_state}="0" SYSFS{type}="0" SYSFS{max_sectors}="240" SYSFS{device_blocked}="0" SYSFS{queue_depth}="1" SYSFS{scsi_level}="3" SYSFS{vendor}=" " SYSFS{model}="USB 2.0M DSC " SYSFS{rev}="1.00" SYSFS{online}="1"
From the output information, look for suitable keys that will not change. Remember that you cannot normally use keys from different directories.
15.5. Consistent Names for Mass Storage Devices
SUSE LINUX comes with scripts that help always assign the same designations to hard disks and other storage devices. /sbin/udev.get_persistent_device_name.sh is a wrapper script. First it calls/sbin/udev.get_unique_hardware_path.sh, which ascertains the hardware path for a specified device. /sbin/udev.get_unique_drive_id.sh also retrieves the serial number. Both outputs are then passed to udev, which creates the symbolic link to the device node under /dev. The wrapper can be used directly in the udev rules. Here is an example for SCSI, which can also be generalized to USB or IDE (write it as one line):
BUS="scsi", PROGRAM="/sbin/udev.get_persistent_device_name.sh", NAME="%k", SYMLINK="%c{1+}"
As soon as a driver has been loaded for a mass storage device, it registers with all the available hard disks with the kernel. Each of them triggers a hotplug block event that calls udev. First, udev reads the rules to ascertain whether a symlink needs to be created.
If the driver is loaded via initrd, the hotplug events are lost. However, all the information is stored in sysfs. The udevstart utility finds all the device files under /sys/block and /sys/class and starts udev.
There is also a start script boot.udev, which recreates all the device nodes during the boot process. However, the start script must be activated through the YaST runlevel editor or with the command insserv boot.udev.