<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
  "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
  <!ENTITY % general-entities SYSTEM "../../general.ent">
  %general-entities;
]>

<sect1 id="ch-scripts-udev">
  <?dbhtml filename="udev.html"?>

  <title>Device and Module Handling on an LFS System</title>

  <indexterm zone="ch-scripts-udev">
    <primary sortas="a-Udev">Udev</primary>
  <secondary>usage</secondary></indexterm>

  <para>In <xref linkend="chapter-building-system"/>, we installed the Udev
  package. Before we go into the details regarding how this works, a brief
  history of previous methods of handling devices is in order.</para>

  <para>Linux systems in general traditionally use a static device creation
  method, whereby a great many device nodes are created under <filename
  class="directory">/dev</filename> (sometimes literally thousands of nodes),
  regardless of whether the corresponding hardware devices actually exist.
  This is typically done via a <command>MAKEDEV</command> script, which
  contains a number of calls to the <command>mknod</command> program with
  the relevant major and minor device numbers for every possible device that
  might exist in the world. Using the Udev method, only those devices which
  are detected by the kernel get device nodes created for them. Because
  these device nodes will be created each time the system boots, they will
  be stored on a <systemitem class="filesystem">tmpfs</systemitem> (a virtual
  file system that resides entirely in system memory). Device nodes do not
  require much space, so the memory that is used is negligible.</para>

  <sect2>
    <title>History</title>

    <para>In February 2000, a new filesystem called <systemitem
    class="filesystem">devfs</systemitem> was merged into the 2.3.46 kernel
    and was made available during the 2.4 series of stable kernels. Although
    it was present in the kernel source itself, this method of creating
    devices dynamically never received overwhelming support from the core
    kernel developers.</para>

    <para>The main problem with the approach adopted by <systemitem
    class="filesystem">devfs</systemitem> was the way it handled
    device detection, creation, and naming. The latter issue, that of
    device node naming, was perhaps the most critical. It is generally
    accepted that if device names are allowed to be configurable, then
    the device naming policy should be up to a system administrator, not
    imposed on them by any particular developer(s). The <systemitem
    class="filesystem">devfs</systemitem> file system also suffers from race
    conditions that are inherent in its design and cannot be fixed
    without a substantial revision to the kernel. It has also been marked
    as deprecated due to a lack of recent maintenance.</para>

    <para>With the development of the unstable 2.5 kernel tree, later
    released as the 2.6 series of stable kernels, a new virtual filesystem
    called <systemitem class="filesystem">sysfs</systemitem> came to be. The
    job of <systemitem class="filesystem">sysfs</systemitem> is to export a
    view of the system's hardware configuration to userspace processes. With
    this userspace-visible representation, the possibility of seeing a
    userspace replacement for <systemitem class="filesystem">devfs</systemitem>
    became much more realistic.</para>

  </sect2>

  <sect2>
    <title>Udev Implementation</title>

    <para>The <systemitem class="filesystem">sysfs</systemitem> filesystem
    was mentioned briefly above. One may wonder how <systemitem
    class="filesystem">sysfs</systemitem> knows about the devices present
    on a system and what device numbers should be used for them. Drivers
    that have been compiled into the kernel directly register their objects
    with <systemitem class="filesystem">sysfs</systemitem> as they are
    detected by the kernel. For drivers compiled as modules, this
    registration will happen when the module is loaded. Once the
    <systemitem class="filesystem">sysfs</systemitem> filesystem is mounted
    (on <filename class="directory">/sys</filename>), data which the built-in
    drivers registered with <systemitem class="filesystem">sysfs</systemitem>
    are available to userspace processes and to <command>udev</command> for
    device node creation.</para>

    <para>The <command>S10udev</command> initscript takes care of creating
    these device nodes when Linux is booted. This script starts by registering
    <command>/sbin/udevsend</command> as a hotplug event handler. Hotplug
    events (discussed below) are not usually generated during this stage,
    but <command>udev</command> is registered just in case they do occur.
    The <command>udevstart</command> program then walks through the
    <systemitem class="filesystem">/sys</systemitem> filesystem and creates
    devices under <filename class="directory">/dev</filename> that match the
    descriptions. For example, <filename>/sys/class/tty/vcs/dev</filename>
    contains the string <quote>7:0</quote> This string is used by
    <command>udevstart</command> to create <filename>/dev/vcs</filename>
    with major number <emphasis>7</emphasis> and minor <emphasis>0</emphasis>.
    The names and permissions of the nodes created under the <filename
    class="directory">/dev</filename> directory are configured according to
    the rules specified in the files within the <filename
    class="directory">/etc/udev/rules.d/</filename> directory. These are
    numbered in a similar fashion to the LFS-Bootscripts package. If
    <command>udev</command> can't find a rule for the device it is creating,
    it will default permissions to <emphasis>660</emphasis> and ownership to
    <emphasis>root:root</emphasis>.</para>

    <para>Once the above stage is complete, all devices that were already
    present and have compiled-in drivers will be available for use. This
    leads us to the devices that have modular drivers.</para>

    <para>Earlier, we mentioned the concept of a <quote>hotplug event
    handler.</quote> When a new device connection is detected by the kernel,
    the kernel will generate a hotplug event and look at the file
    <filename>/proc/sys/kernel/hotplug</filename> to determine the userspace
    program that handles the device's connection. The <command>udev</command>
    bootscript registered <command>udevsend</command> as this handler. When
    these hotplug events are generated, the kernel will tell
    <command>udev</command> to check the <filename
    class="directory">/sys</filename> filesystem for the information
    pertaining to this new device and create the <filename
    class="directory">/dev</filename> entry for it.</para>

    <para>This brings us to one problem that exists with
    <command>udev</command>, and likewise with <systemitem
    class="filesystem">devfs</systemitem> before it. It is commonly
    referred to as the <quote>chicken and egg</quote> problem. Most
    Linux distributions handle loading modules via entries in
    <filename>/etc/modules.conf</filename>. Access to a device node causes
    the appropriate kernel module to load. With <command>udev</command>,
    this method will not work because the device node does not exist until
    the module is loaded. To solve this, the <command>S05modules</command>
    bootscript was added to the LFS-Bootscripts package, along with the
    <filename>/etc/sysconfig/modules</filename> file. By adding module
    names to the <filename>modules</filename> file, these modules will be
    loaded when the computer starts up. This allows <command>udev</command>
    to detect the devices and create the appropriate device nodes.</para>

    <para>Note that on slower machines or for drivers that create a lot
    of device nodes, the process of creating devices may take a few
    seconds to complete. This means that some device nodes may not be
    immediately accessible.</para>

  </sect2>

  <sect2>
    <title>Handling Hotpluggable/Dynamic Devices</title>

    <para>When you plug in a device, such as a Universal Serial Bus (USB)
    MP3 player, the kernel recognizes that the device is now connected and
    generates a hotplug event. If the driver is already loaded (either
    because it was compiled into the kernel or because it was loaded via
    the <command>S05modules</command> bootscript), <command>udev</command>
    will be called upon to create the relevant device node(s) according to
    the <systemitem class="filesystem">sysfs</systemitem> data available in
    <filename class="directory">/sys</filename>.</para>

    <para>If the driver for the just plugged in device is available as a
    module but currently unloaded, the Hotplug package will load the
    appropriate module and make this device available by creating the
    device node(s) for it.</para>

  </sect2>

  <sect2>
    <title>Problems with Creating Devices</title>

    <para>There are a few known problems when it comes to automatically
    creating device nodes:</para>

    <para>1) A kernel driver may not export its data to <systemitem
    class="filesystem">sysfs</systemitem>.</para>

    <para>This is most common with third party drivers from outside the
    kernel tree. Udev will be unable to automatically create device nodes
    for such drivers. Use the <filename>/etc/sysconfig/createfiles</filename>
    configuration file to manually create the devices. Consult the
    <filename>devices.txt</filename> file inside the kernel documentation
    or the documentation for that driver to find the proper major/minor
    numbers.</para>

    <para>2) A non-hardware device is required. This is most common with
    the Advanced Linux Sound Architecture (ALSA) project's Open Sound
    System (OSS) compatibility module. These types of devices can be
    handled in one of two ways:</para>

    <itemizedlist>
      <listitem>
        <para>Adding the module names to
        <filename>/etc/sysconfig/modules</filename></para>
      </listitem>
      <listitem>
        <para>Using an <quote>install</quote> line in
        <filename>/etc/modprobe.conf</filename>. This tells the
        <command>modprobe</command> command <quote>when loading this
        module, also load this other module, at the same time.</quote>
        For example:</para>

<screen><userinput>install snd-pcm modprobe -i snd-pcm ; modprobe \
    snd-pcm-oss ; true</userinput></screen>

        <para>This will cause the system to load both the
        <emphasis>snd-pcm</emphasis> and <emphasis>snd-pcm-oss</emphasis>
        modules when any request is made to load the driver
        <emphasis>snd-pcm</emphasis>.</para>
      </listitem>
    </itemizedlist>

  </sect2>

  <sect2>
    <title>Useful Reading</title>

    <para>Additional helpful documentation is available at the following
    sites:</para>

    <itemizedlist>
      <listitem>
        <para remap="verbatim">A Userspace Implementation of <systemitem class="filesystem">devfs</systemitem>
        <ulink url="http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf"/></para>
      </listitem>
      <listitem>
        <para remap="verbatim">udev FAQ
        <ulink url="http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-FAQ"/></para>
      </listitem>
      <listitem>
        <para remap="verbatim">The Linux Kernel Driver Model
        <ulink url="http://public.planetmirror.com/pub/lca/2003/proceedings/papers/Patrick_Mochel/Patrick_Mochel.pdf"/></para>
      </listitem>
    </itemizedlist>

  </sect2>

</sect1>
