Linux System Startup

by Rick Mann

Today, you can purchase a Linux distribution, install it and use it, all without really understanding much about the operating system itself. For those perhaps new to Linux who want to know a bit more about their OS, this article looks inside the startup sequence of Linux on a PC.

The techie word for starting up a computer is "bootstrapping", and the short version is "booting" or "boot". The initial part of this booting process is performed by code stored in ROM. This code is general in nature and is not specific to Linux. Its task is to load the Linux-specific boot loader and turn control of the system over to it.

Boot Loaders

The boot loader is the program loaded by the ROM. It is either the BIOS (Basic Input/Output System) on the motherboard or device-specific code, as might be found on a SCSI disk controller board. There are two popular boot loaders for PCs. LILO, short for Linux loader, is the traditional loader, while GRUB, short for grand unified bootloader, is the newer one. Each program has the task of grabbing some configuration information, loading the Linux (or other) kernel and turning over control to the OS.

The most significant difference between LILO and GRUB is how it gets the configuration information. Configuration for LILO is saved in a static form by running the lilo command. This information is written to either the master boot record (MBR) of the disk or to the boot record of the Linux root partition. The configuration information used by the lilo command normally is stored in /etc/lilo.conf. Here is a sample configuration file:


boot=/dev/hda   # boot loader to MBR
root=/dev/hda1  # root partition
install=/boot/boot.b
map=/boot/map
delay=50        # 5 second delay before auto-boot
image=/vmlinuz  # kernel
  label=linux   # name to refer to entry
  read-only
image=/vmlinuz.old      # backup entry
  label=old
  read-only

In this example, two possible kernels could boot: vmlinuz and vmlinuz.old. At the LILO prompt, you can select the one you want by entering linux to select the current one or old to select the backup one. Pressing the TAB key at the LILO prompt lists these options. If you rebuild your kernel or want to make any other change, you need to re-run the lilo command to re-read the configuration file and then re-install LILO with this new configuration information.

GRUB reads the configuration file at boot time. The MBR for GRUB is only 512 bytes. The portion of GRUB installed in the MBR does some basic initialization of the system, figures out how to access the boot drive and then loads the rest of GRUB from the drive.

GRUB is installed by the grub-install program. See the GRUB man page for more details. The GRUB info page also is helpful. The configuration file generally is located in the /boot/grub directory, although SUSE puts it in menu.lst and Red Hat stores it in grub.conf. Here is a sample configuration file:


default 0
timeout 8
gfxmenu (hd0,1)/boot/message

title Linux
    kernel (hd0,1)/boot/vmlinuz root=/dev/hda2 desktop showopts
    initrd (hd0,1)/boot/initrd

title Failsafe
    kernel (hd0,1)/boot/vmlinuz root=/dev/hda2 showopts ide=nodma apm=off acpi=o
ff vga=normal nosmp noapic maxcpus=0 3
    initrd (hd0,1)/boot/initrd

title Memory Test
    kernel (hd0,1)/boot/memtest.bin

If you are sharing the computer with a proprietary OS from Redmond, take note that the proprietary system doesn't realize other operating systems are available. So, when you install that system after Linux, it simple overwrites the entire MBR. If you install the proprietary OS software first and then Linux, all should be okay and you should be able to boot either OS.

Run Levels

Run levels offer you an array of system configurations. Unless it is told otherwise, the system boots up at the default runlevel, which typically is level 3 or level 5. You can alter this behavior by entering the label name in LILO. In GRUB, you can enter the word boot, followed by the word single at the boot loader prompt.

There are seven standard runlevels, 0 through 6. Level 0 means shutdown, level 1 is single-user mode and level 6 means reboot. The other levels are available at your discretion to set up various system configurations. The most typical is to use runlevel 3, which is a fully operational system without the GUI (X) running. Level 5 is similar to level 3, only it runs the GUI. Many systems also have a runlevel called S, which is like runlevel 1 but requires the root password to be entered. This is available for security reasons.

The contents of the file /etc/inittab determine what action is to be taken at each runlevel, and it also specifies the default runlevel. Here is a sample of what might appear in /etc/inittab:


#
# /etc/inittab
#
# This is the main configuration file of /sbin/init, which
# is executed by the kernel on startup.
#

# The default runlevel
id:5:initdefault:

# /etc/init.d/rc takes care of runlevel handling
#
# runlevel 0  is  System halt   (Do not use this for initdefault!)
# runlevel 1  is  Single user mode
# runlevel 2  is  Local multiuser without remote network (e.g. NFS)
# runlevel 3  is  Full multiuser with network
# runlevel 4  is  Not used
# runlevel 5  is  Full multiuser with network and xdm
# runlevel 6  is  System reboot
#
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6

# what to do in single-user mode
ls:S:wait:/etc/init.d/rc S
~~:S:respawn:/sbin/sulogin

# what to do when CTRL-ALT-DEL is pressed
ca::ctrlaltdel:/sbin/shutdown -r -t 4 now

# getty-programs for the normal runlevels
# :::
# The "id" field  MUST be the same as the last
# characters of the device (after "tty").
1:2345:respawn:/sbin/mingetty --noclear tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

The line id:5:initdefault: sets the default runlevel to 5. The lines in the form of l1:1:wait:/etc/init.d/rc 1 invoke the script /etc/init.d/rc passing it the runlevel as an argument. This script then starts the processes associated with the specific runlevel and stops other processes. All of the scripts to control each process also are located in the /etc/init.d directory.

Typically, the details of which processes should be started and stopped at each run level are located in sub-directories of /etc/init.d, for example, rc5.d for runlevel 5. In each of these runlevel-specific directories, symbolic links are used to identify the processes. Link names starting with "K" refer to processes that are to be stopped (killed), while link names starting with "S" refer to those that are to be started. The links are accessed alphabetically, which means the kill scripts are run first. The order of the scripts within the kill and start lists are controlled by using a two-digit number immediately following the K or S.

I said that these process start/stop details typically are handled in this way, as this is the standard way to handle this information. Some vendors use slightly different schemes, however, but in all cases, the generainit program is what controls the whole process. If you are familiar with how UNIX handles starting up, generainit is similar to System V Init.

If no problems are encountered along the way, your system now should be at your chosen runlevel. Once the system is up and running, you can change runlevels by logging on as root and using the init command. For example, to change to runlevel 3, you would enter init 3.

Copyright (c) 2004, Rick Mann. Originally published in Linux Gazette issue 98. Copyright (c) 2004, Specialized Systems Consultants, Inc.

Rick Mann has been programming in C and working with POSIX-compliant operating systems for over 12 years.

Load Disqus comments