Linux Root Filesystem Primer

From Buici

Jump to: navigation, search

In order to build a root filesystem for Linux, you must be familiar with the way the system boots. This primer focuses on the part of the boot process as the kernel transitions into executing user-mode applications. See the ApexBootloader for information about early system startup.

The named source files refer to version 2.6.11 of the kernel. Other kernel versions may vary in some details, but the concepts should continue to hold true.

Contents

The First Program

The kernel makes it's first transition to user-mode in one of two places. When the filesystem is loaded as an initrd, it executes the program /linuxrc from the file init/do_mounts_initrd.c. But this is a fleeting reference. The normal transition to user-mode occurs in init/main.c where the kernel executes a series of programs until one of them doesn't return. These programs include /sbin/init, /etc/init, /bin/init, and /bin/sh. If a program is given to the kernel on the command line as init=filename, then the kernel will first attempt to execute filename before checking for the others.

In order for this first program to execute, several features must be present in the root filesystem. This first step is the most difficult because there tends to be few diagnostics explaining the reason that the kernel cannot start the first program.

Init

On most system, the first program will be init or some relative. This isn't required, but it does provide a few important features. We'll assume you are using busybox init which is a reasonable subset of the sysv init program. The main thing it lacks is support for run-levels.

There are two important things that init does.

  • Invokes the initialization scripts.
  • Spawns interface shells.

The default inittab for the busybox init looks like this.

::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh

On system startup, it executes /etc/init.d/rcS to perform the one-time system initializations. This is usually either a C program, a shell script, or a shell script that calls other shell scripts.

The second line opens the default console device and asks the user to press the Enter key to start an interactive shell. Once started, it will usually complain that the shell cannot access the tty and therefore it is disabling job control. This can be fixed by explicitly setting the serial device. Note that the name of the serial device is specific to the kernel driver.

::sysinit:/etc/init.d/rcS
ttyAM0::askfirst:-/bin/sh

Shared Libraries

Most systems require shared link libraries. Shared libraries serve two purposes: LGPL compliance in allowing users to change the library without needing access to program sources, and disk/memory space efficiency.

The program ldd will tell you which libraries a given executable requires at runtime. But, this program can only be run against executables for the same target as the host. In other words, it cannot read ARM compiled programs when it is being run on a ix86 host. There is an alternative.

If you don't know which libraries are needed by the init program, use strings and grep. The double backslash escapes to a single backslash which prevents grep from interpreting the period as a regex meta-character.

# strings target/sbin/init | grep \\.so
/lib/ld-linux.so.2
libc.so.6

In this case, we appear to need only the dynamic linking loader, and the C library.

Devices

For user applications to have access to all of the physical devices, the /dev directory needs have the necessary files. The necessary and sufficient set of files for a particular system depends on the target hardware. Below are the files

total 0
brw-r--r--   1 root     root       3,   0 May 20 07:43 hda
brw-r--r--   1 root     root       3,   1 May 20 07:43 hda1
brw-r--r--   1 root     root       3,   2 Jun  2 13:46 hda2
brw-r--r--   1 root     root       3,   3 Jun  2 13:46 hda3
brw-r--r--   1 root     root       7,   0 May 20 07:43 loop0
brw-r--r--   1 root     root       7,   1 Jun  2 13:47 loop1
crw-r--r--   1 root     root       1,   3 May 20 07:42 null
crw-r--r--   1 root     root       5,   0 May 20 07:43 tty
crw-r--r--   1 root     root       4,   1 May 20 07:43 tty1
crw-r--r--   1 root     root       1,   5 May 20 07:42 zero

The /dev/console is needed by the linuxrc program. It isn't clear that anything else is required.

Supporting ldconfig

It is a good idea for there to be an /etc/ld.so.conf to keep ldconfig from complaining. It will search /lib and /usr/lib directories automatically. It may be necessary to add the X11 library directory.

Mounts

Many programs require /proc to be mounted. It's a good idea to do this early. Mounting /sys doesn't hurt either. It may be useful to mount /tmp in ram, but this depends on the availability of memory.

The easy way to handle this is to include an /etc/fstab file and call mount -a in the startup scripts. Here is a example fstab.

# /etc/fstab
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0

Init Scripts

There is no requirement that init scripts be used to initialize the system. It is a common convention, but may be unwarranted excess for an embedded system.

Consider the constraints. Init scripts provide convenient mechanisms for adding features to the system. The order of execution is well defined. On the down side, each script requires at least one block of storage in the filesystem. Each scripts will require an invocation of the shell. It is usually worth spending a couple of disk blocks and a few milliseconds at startup for the sake of init scripts if the system will have any upgradability.

Niceties

Contents Of The Initial Ramdisk

The files that you will need on the ramdisk are the minimum requirements to be able to execute any commands.

  • /linuxrc The script that is run to mount the msdos file system (see below).
  • /lib/* The dynamic linker and the libraries that the programs need.
  • /etc/* The cache used by the dynamic linker (not strictly needed, but does stop it complaining).
  • /bin/* A shell interpreter (ash because it is smaller than bash. The mount and losetup programs for handling the DOS disk and setting up the loopback devices.
  • /dev/* The devices that will be used. You need /dev/zero for ld-linux.so, /dev/hda* to mount the msdos disk and /dev/loop* for the lopback device.
  • /mnt An empty directory to mount the msdos disk on.

The initial ramdisk that I used is listed below, the contents come to about 800kB when the overhead of the filesystem are taken into account.

total 18
drwxr-xr-x   2 root     root         1024 Jun  2 13:57 bin
drwxr-xr-x   2 root     root         1024 Jun  2 13:47 dev
drwxr-xr-x   2 root     root         1024 May 20 07:43 etc
drwxr-xr-x   2 root     root         1024 May 27 07:57 lib
-rwxr-xr-x   1 root     root          964 Jun  3 08:47 linuxrc
drwxr-xr-x   2 root     root        12288 May 27 08:08 lost+found
drwxr-xr-x   2 root     root         1024 Jun  2 14:16 mnt

./bin:
total 168
-rwxr-xr-x   1 root     root        60880 May 27 07:56 ash
-rwxr-xr-x   1 root     root         5484 May 27 07:56 losetup
-rwsr-xr-x   1 root     root        28216 May 27 07:56 mount
lrwxrwxrwx   1 root     root            3 May 27 08:08 sh -> ash

./dev:
total 0
brw-r--r--   1 root     root       3,   0 May 20 07:43 hda
brw-r--r--   1 root     root       3,   1 May 20 07:43 hda1
brw-r--r--   1 root     root       3,   2 Jun  2 13:46 hda2
brw-r--r--   1 root     root       3,   3 Jun  2 13:46 hda3
brw-r--r--   1 root     root       7,   0 May 20 07:43 loop0
brw-r--r--   1 root     root       7,   1 Jun  2 13:47 loop1
crw-r--r--   1 root     root       1,   3 May 20 07:42 null
crw-r--r--   1 root     root       5,   0 May 20 07:43 tty
crw-r--r--   1 root     root       4,   1 May 20 07:43 tty1
crw-r--r--   1 root     root       1,   5 May 20 07:42 zero

./etc:
total 3
-rw-r--r--   1 root     root         2539 May 20 07:43 ld.so.cache

./lib:
total 649
lrwxrwxrwx   1 root     root           18 May 27 08:08 ld-linux.so.1 -> ld-linux.so.1.7.14
-rwxr-xr-x   1 root     root        21367 May 20 07:44 ld-linux.so.1.7.14
lrwxrwxrwx   1 root     root           14 May 27 08:08 libc.so.5 -> libc.so.5.3.12
-rwxr-xr-x   1 root     root       583795 May 20 07:44 libc.so.5.3.12

./lost+found:
total 0

./mnt:
total 0

--Elf 17:13, 6 April 2006 (PDT)

Personal tools