====== Linux Udev Presentation ======
This is the full text of a presentation prepared for the August meeting of the
San Antonio Linux Users Group. For more information about satlug go to
www.satlug.org.
Please feel free to download the actual openoffice presentation [[http://www.mccoyfam.net/files/udev-presentation.sxi|here]].
//Note: I still need to upload the last section of this page, sorry it has taken so long.// **:)**
====== History of devices in Unix and Linux ======
The basic design of the Unix system is that //everything should look like a
file//. Any program that needs to send or receive information to a device can
open it, read from it (or write to it), and close it using the simple
programming interfaces available for all files.
Traditionally, almost all devices attached to a Unix-type system are available
under the ''/dev'' directory.
But, how do they get there?
===== Device nodes =====
The traditional Unix way of creating device nodes in ''/dev'' is through //major
and minor numbers//. Major and minor numbers are part of the kernel API for
devices. A major number refers to a device class, and a minor number refers
to a specific device of that category. For example, look at the major/minor
numbers for hard drives (columns 5 and 6 in an ''ls -l'' listing):
[neptune ~]$ ls -l /dev/hd*
brw-rw---- 1 root disk 3, 0 2005-07-14 13:58 /dev/hda
brw-rw---- 1 root disk 3, 1 2005-07-14 13:58 /dev/hda1
brw-rw---- 1 root disk 3, 2 2005-07-14 13:58 /dev/hda2
brw-rw---- 1 root disk 3, 3 2005-07-14 13:58 /dev/hda3
brw-rw---- 1 root disk 3, 5 2005-07-14 13:58 /dev/hda5
brw-rw---- 1 root disk 3, 6 2005-07-14 13:58 /dev/hda6
brw-rw---- 1 root disk 3, 64 2005-07-14 17:02 /dev/hdb
brw-rw---- 1 root disk 3, 65 2005-07-14 17:02 /dev/hdb1
brw-rw---- 1 root optical 22, 0 2005-07-14 17:02 /dev/hdc
===== Creating device nodes =====
Tradtionally, the way to create a device node in ''/dev'' was to use the program
''mknod (1)''.
[neptune ~]$ mknod --help
Usage: mknod [OPTION]... NAME TYPE [MAJOR MINOR]
Of course, you had to know what type of device you had (block, character,
special, FIFO) and the major and minor numbers for the device.
You also had to set up the permissions for the device node after creating it.
===== Problems with the tried and true =====
The old way was not very flexible, from a user's standpoint. It was designed
to be set up once and then never changed. Typically, //all// device nodes
possible were set up in ''/dev'' by the OS vendor, leading to a //very// large
number of devices in ''/dev''. The ''/dev'' directory contained many hundreds or
thousands of entries for devices that weren't even attached to the system.
Devices could not be created "on-the fly" when new hardware was attached to the system. Plug and play devices like USB devices weren't handled well, if at all.
Running out of subdevices, terminal lines for example, was a problem. If you
had only allocated a certain number of terminal entries in ''/dev'', and you
attached more terminals, you could not use them until you created more device
nodes.
===== Kernel-space device management: devfs =====
The first device manager for linux was devfs. Devfs is a file system (like
ext3 or reiserfs) that could create and manage device nodes. It had to be
mounted at ''/dev'' for standard device usage, but it could also be mounted in
other places in the file tree.
Devfs allowed for automatic loading of kernel modules whenever a device node
was accessed.
Devfs seemed to be a good answer to the problems, but it wasn't quite as
flexible as the users wanted it to be.
===== Some problems with devfs =====
Some of the problems of the non-managed ''/dev'' directory still existed, like the problem of having a huge ''/dev'' directory.
The feature of devfs to autoload a module when the device node was accessed
turned out to cause problems with some modules when a device node was accessed
without having a device attached to it.
The most important problem was that since devfs was part of the kernel, adding
new device information was //only// possible by the kernel maintainers. The
only way for users to get new devices added to their devfs system was by
upgrading their kernel!
===== User-Space Device Manager: udev =====
And now, udev to the rescue!
udev is a user-mode daemon that has special permission by the kernel to work in
the ''/dev'' directory. It is started at boot time and it is responsible for
adding/removing device nodes, setting up permissions, symlinks, etc. Udev
works with the hotplug system to manage devices on the fly as kernel modules
get loaded or unloaded.
Since udev is only resonsible for maintenance of the ''/dev'' tree, another
system was created to manage module loading and unloading on the fly. The
hotplug system works with udev to recreate the functionality of devfs without
the problems that devfs had.
Since udev is maintained outside of the kernel tree, updates to udev can be
made rapidly, allowing new devices to be recognized much sooner than by waiting
to upgrade the kernel.
====== The Benefits of Using udev ======
* The combination of udev, hotplug, and sysfs allows for a much more flexible base to build a system on.
* Devices can be given special names or permissions without modifying the kernel source.
* Several devices can be bound together to create one device node (more on that later!!!)
* Hotplugging devices works automagically, finally!!
* Smaller ''/dev'' to work with (uses less memory than devfs)
* **Devfs support is officially deprecated by the kernel team, and will be removed from the 2.6 kernel in the future.**
====== Migrating from a devfs to a udev System ======
===== Prerequisites =====
Using udev requires that your kernel and your distribution support udev,
hotplug, and the ''/sys'' file system. **Check with your distribution's
support for more information about installing udev and hotplug support.** Your
distribution's initscript package should also support udev, since it must be
able to load ''/sbin/udevd'' at boot time.
Building a udev-enabled kernel is quite simple. The only kernel option that
you must enable is CONFIG_HOTPLUG. Once you are sure that udev is
working properly, you can disable devfs support in your kernel permanently.
If devfs is compiled into your kernel, devfs will be used unless you pass a
boot-time kernel parameter to disable devfs.
===== Booting a udev Kernel =====
==== Check to make sure that your kernel supports hotplug ====
[neptune ~]$ cat /proc/config.gz | gunzip | grep -i "CONFIG_HOTPLUG"
CONFIG_HOTPLUG=y
CONFIG_HOTPLUG_PCI_PCIE=m
# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI_FAKE=m
CONFIG_HOTPLUG_PCI_COMPAQ=m
# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
CONFIG_HOTPLUG_PCI_IBM=m
CONFIG_HOTPLUG_PCI_ACPI=m
CONFIG_HOTPLUG_PCI_ACPI_IBM=m
CONFIG_HOTPLUG_PCI_CPCI=y
CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
CONFIG_HOTPLUG_PCI_SHPC=m
# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
==== Check to make sure you mount ''/sys'' as a sysfs filesystem ====
NOTE: Some distributions mount ''/sys'' automatically during their initscripts
if the sysfs option is enabled in the kernel, others add an entry in fstab.
[neptune ~]$ mount | grep /sys
none on /sys type sysfs (rw)
If you do not have ''/sys'' loaded, make sure that sysfs support is enabled in
your kernel. Use grep to look for "SYSFS" in ''/proc/config.gz'' or for
"sysfs" in ''/proc/filesystems''.
If your distribution doesn't automatically mount ''/sys'' in the initscripts,
add an entry to ''/etc/fstab'' like this:
sysfs /sys sysfs defaults 0 0
==== Check to make sure hotplug is installed ====
[neptune ~]$ ls /sbin/hotplug /sbin/udevd
/sbin/hotplug
If hotplug and udev are not installed, you can probably use your package
management tools to install them (yum on Fedora, apt-get on debian, emerge on
gentoo, pacman on arch, etc...). If not, you can download hotplug and udev at
http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/ and install them using the standard "''make ; make install''" duo. The README files in these tarballs have a lot of good information about using hotplug and udev.
==== Check to make sure that your fstab file is good ====
One of the changes using devfs was that the way the disk drives were labelled
changed. The old naming scheme was the familiar ''/dev/hda1'', which changed
to ''/dev/discs/disc0/part1''. This scheme worked fine, unless you had mixed
IDE and SCSI devices on your system and added or removed drives.
Udev reverts to the original naming scheme (thankfully), but a lot of
distributions have configured udev to allow allow both devfs and udev names.
If you try to boot using udev and you cannot mount your partitions properly, or
if you want to use a udev-only system, you will need to modify your
''/etc/fstab'' to use the udev naming scheme for your hard drives.
# devfs naming scheme
/dev/discs/disc0/part1 /boot ext3 sync,noatime 0 0
/dev/discs/disc0/part2 swap swap defaults,noatime 0 0
/dev/discs/disc0/part5 / reiserfs defaults,noatime 0 0
# udev naming scheme
/dev/hda1 /boot ext3 sync,noatime 0 0
/dev/hda2 swap swap defaults,noatime 0 0
/dev/hda5 / reiserfs defaults,noatime 0 0
Some distributions enable devfs in the kernel, but disable the
CONFIG_DEVFS_MOUNT option. In that case, ''/dev'' is not automatically mounted
by the kernel at boot and there will be a line in ''/etc/fstab'' like ''devfs
/dev devfs defaults 0 0''. Comment out this line by adding a "#" to the front.
===== Booting the kernel =====
The only thing left is to tell the kernel not to use devfs. This is done by
adding the ''defvs=nomount'' option to the kernel boot parameters in either
''/boot/grub/grub.conf'' or ''/etc/lilo.conf''.
# a portion of the /boot/grub/grub.conf
title Linux 2.6 (using udev)
root (hd0,0)
kernel /vmlinuz26 root=/dev/hda5 ro vga=773 devfs=nomount single
title Linux 2.6 (using devfs)
root (hd0,0)
kernel /vmlinuz26 root=/dev/hda5 ro vga=773
# a portion of the /etc/lilo.conf file
# Linux 2.6 (using udev)
image = /boot/vmlinuz26
append = "root=/dev/hda5 ro vga=773 devfs=nomount single"
label = linux-devfs
# Linux 2.6 (using devfs)
image = /boot/vmlinuz26
label = linux-devfs
append = "root=/dev/hda5 ro vga=773"
**Don't forget to run the ''lilo'' command before you reboot!!**
**NOTE: it is always best to reboot into single user mode when trying out a feature that is likely to break your system if not configured properly.**
===== Did it Work? =====
Reboot (into single-user mode the first time!)
Depending on your distribution, you should have some sort of bootup message
saying that the udev system is starting. You can verify that udev started by
checking to make sure that ''/dev'' is not mounted as a devfs filesystem.
[neptune ~]$ mount
/dev/hda5 on / type reiserfs (rw,noatime)
none on /proc type proc (rw)
none on /sys type sysfs (rw)
none on /dev/pts type devpts (rw)
none on /dev/shm type tmpfs (rw)
tmpfs on /tmp type tmpfs (rw)
/dev/hda1 on /boot type ext3 (rw,sync,noatime)
/dev/hda6 on /home type reiserfs (rw,noatime)
/dev/hdb1 on /shared type reiserfs (rw,noatime)
none on /proc/bus/usb type usbfs (rw)
A listing of the files in /dev should also give you a clue. There should only
be about 90-100 files and directories in the top-level of /dev. In particular,
there will only be enough /dev/hd* or /dev/sd* devices to cover the actual
devices that you have attached to your system (or /dev/discs/* if you like that
sort of thing).
===== It Worked! What Next? =====
One minor "gotcha" for a devfs to udev migration is that udev doesn't always
create a ''/dev/mouse'' symlink for you, so if you have xorg.conf configured to
use a mouse at ''/dev/mouse'', you will either have to change xorg.conf to use
the mouse device at ''/dev/input/mice'' or make a symlink from ''/dev/mouse'' to
''/dev/input/mice''.
[neptune ~]$ cd /dev
[neptune /dev]$ ln -s input/mice mouse
[neptune /dev]$ ls -l mouse
lrwxrwxrwx 1 root root 10 2005-07-14 23:30 mouse -> input/mice
====== udev Tricks ======
===== USB Thumb Drive =====
==== Modifying the Config Files ====
==== Did it Work? ====
===== USB Printer =====
==== Modifying the Config Files ====
==== Did it Work? ====
====== The Future is Now (Project Utopia) ======
===== Project Utopia =====
===== Real Plug and Play =====