Ruminations on Udev, null and console

Neal Murphy neal.p.murphy at alum.wpi.edu
Fri Feb 25 14:09:08 PST 2011


On Friday 25 February 2011 15:02:23 Bruce Dubbs wrote:
> It looks like the process is:
> 
> 1.  Use null and console at the start.
> 2.  Mount a tmpfs on /dev hiding the original null and console devices.
> 3.  Create all new devices, including null, on the tmpfs via udev and
> the boot script.
> 
> Newer versions of udev or the kernel may make some of these procedures
> unnecessary, but they don't hurt anything.  A device node takes up 1
> directory entry and no additional space.
> 
> I don't understand what appears to be a sense of urgency in your post.
> What are the drawbacks of the procedure as is?

You are quite right. Your three steps work fine and hurt nothing. The drawback 
is slightly elevated code complexity in building and preparing the system, 
booting it, as well as the effort to keep and maintain that code.

Enabling CONFIG_DEVTMPFS_MOUNT in the kernel (2.6.32+, I believe) reduces the 
steps to:
  1. Mount devtmpfs on /dev; the kernel populates it with devices it knows
  2. Run udev to 'take over' those nodes and populate it with everything else

You eliminate the code to pre-populate /dev, as well as other conditional 
'setup' code; also eliminated are special programs needed to make early 
userspace programs work properly. I eliminated 100-200 lines of shell script 
by taking this route. You have an automatic 'proper' user environment in early 
userspace; no more hoops to jump through--shells and other programs 'just 
work'. A proper early userspace environment makes building a 'live' system 
almost trivial.

My runtime 'init' script is 62 lines, ending with running klibc's run-init to 
switch to HD operation. It's 39 lines after eliminating blank lines and 
informational progress echos. It works on iron and in QEMU/KVM. HD operations 
begin with all needed system FSen mounted and /dev fully populated:
  - /dev
  - /dev/pts
  - /proc
  - /sys
  - /proc/bus/usb
My firewall doesn't use /dev/shm and there may be a few more kernel FSen 
available. It also creates six dirs in rootfs that could be made when the 
initramfs is built; these six lines could be eliminated (technically: moved 
elsewhere).

One point is that the kernel and udev can do a lot of work for the user at 
little cost; there is no need to create any nodes in /dev. Perhaps another 
point is that the initramfs' init script now needs only make a few dirs as 
needed, mount system FSen, run and kill udev, mount-move those system FSen 
from rootfs to the HD's root, mount the rest of the system FSen, and then 
switch operation to the HD. It really becomes almost trivial; still somewhat 
tedious, but real easy. 

Here's my runtime-init script, which undoubtedly would need tweaking to work 
with LFS. (I split three lines to fit email):

======================
#!/bin/bash

/sbin/depmod -a

echo "Loading, please wait..."

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir -m 0777 /tmp
[ -d /var/lock ] || mkdir -p -m 755 /var/lock

# Mount proc, sys, dev
echo "Mounting /proc, /sys"
/bin/mount -t proc proc /proc
/bin/mount -t sysfs sysfs /sys

echo "Mounting devtmpfs"
/bin/mount -t devtmpfs devtmpfs /dev

# Populating dev
/sbin/udevd --daemon
/sbin/udevadm trigger
/sbin/udevadm settle

if [ -d /proc/bus/usb ]; then
  echo "Mounting proc/bus/usb"
  /bin/mount -t usbfs usbfs /proc/bus/usb
fi

# Load any modules explicitly required
test -e /etc/modules && egrep -v "^$|^#" /etc/modules \
  | while read a; do modprobe $a; done

# Switch to hard drive and start the system
/bin/mount /harddisk -o ro

# Stop udevd; missed events will be caught later
for proc in /proc/[0-9]*; do
    [ -x $proc/exe ] || continue
    [ "$(/usr/lib/klibc/bin/readlink $proc/exe)" != /bin/udevd ] \
      || kill ${proc#/proc/}
done

echo "1 4 1 7" >/proc/sys/kernel/printk

if [ -d /proc/bus/usb ]; then
  /bin/umount /proc/bus/usb
fi
/bin/mount -n -o move /dev /harddisk/dev
/bin/mkdir -p /harddisk/dev/pts
/bin/mount -t devpts devpts /harddisk/dev/pts

/usr/lib/klibc/bin/nuke /dev
/bin/ln -s /harddisk/dev /dev

/bin/mount -n -o move /sys /harddisk/sys
/bin/mount -n -o move /proc /harddisk/proc
if [ -d /harddisk/proc/bus/usb ]; then
  /bin/mount -t usbfs usbfs /harddisk/proc/bus/usb
fi

exec /usr/lib/klibc/bin/run-init /harddisk /sbin/init \
  </harddisk/dev/console >/harddisk/dev/console 2>&1
======================



More information about the lfs-support mailing list