Behind the Scenes of the Boot Process

NoteNote
 

This section looks at the x86 boot process, in particular. Depending on your system's architecture, your boot process may be slightly different. However, once the kernel is found and loaded by the system, the default Red Hat Linux boot process is identical across all architectures. Please see the section called Differences in the Boot Process of Other Architectures for more information on a non-x86 boot process.

When a computer is booted, the processor looks at the end of the system memory for the BIOS (Basic Input/Output System) and runs it. The BIOS program is written into read-only permanent memory and is always available for use. The BIOS provides the lowest level interface to peripheral devices and controls the first step of the boot process.

The BIOS tests the system, looks for and checks peripherals, and then looks for a drive to use to boot the system. Usually, it checks the floppy drive (or CD-ROM drive on many newer systems) for bootable media, if present, and then it looks to the hard drive. The order of the drives used for booting is usually controlled by a particular BIOS setting on the system. Once Red Hat Linux is installed on a hard drive of a system, the BIOS looks for a Master Boot Record (MBR) starting at the first sector on the first hard drive, loads its contents into memory, and passes control to it.

This MBR code then looks for the first active partition and reads the partition's boot record. The boot record contains instructions on how to load the boot loader, LILO (LInux LOader). The MBR then loads LILO, which takes over the process (if LILO is installed in the MBR). In the default Red Hat Linux configuration, LILO uses the settings in the MBR to display boot options and allow for user input on which operating system to actually start up.

But this begs the question: How does LILO in the MBR know what to do when the MBR is read? LILO actually has already written the instructions there through the use of lilo with the /etc/lilo.conf configuration file.

Options in /etc/lilo.conf

Most of the time, you will have no need to change the Master Boot Record on your hard drive unless you need to boot a newly installed operating system or are looking to use a new kernel. If you do need to create a new MBR using LILO but using a different configuration, you will need edit /etc/lilo.conf and run lilo again.

WarningWarning
 

If you are planning to edit /etc/lilo.conf, be sure to make a backup copy of the file before making any changes. Also, be sure that you have a working boot floppy available so that you will be able to boot the system and make changes to the MBR if there is a problem. See the man pages for mkbootdisk for more information on creating a boot disk.

The file /etc/lilo.conf is used by lilo to determine which operating system(s) to utilize or which kernel to start, as well as to know where to install itself (for example, /dev/hda for the first IDE hard drive). A sample /etc/lilo.conf file looks like this:

boot=/dev/hda
map=/boot/map
install=/boot/boot.b
prompt
timeout=50
message=/boot/message
lba32
default=linux

image=/boot/vmlinuz-2.4.0-0.43.6
	label=linux
	initrd=/boot/initrd-2.4.0-0.43.6.img
	read-only
	root=/dev/hda5

other=/dev/hda1
	label=dos

This example shows a system configured to boot two operating systems: Red Hat Linux and DOS. Here is a deeper look at a few of the lines of this file (your /etc/lilo.conf may look a little different):

LILO then shows the Red Hat Linux initial screen with the different operating systems or kernels it has been configured to boot. If you only have Red Hat Linux installed and have not changed anything in /etc/lilo.conf, you will only see linux as an option. If you have set up LILO to boot other operating systems as well, this screen is your chance to select what operating system will boot. Use your arrow keys to highlight the operating system and press [Enter]

If you would like to have a command prompt to enter commands to LILO, press [Cntl]-[X]. LILO displays a LILO: prompt on the screen and waits for a preset period of time for input from the user. (The amount of time LILO waits is set by the timeout line in the /etc/lilo.conf file.) If your /etc/lilo.conf is set to give LILO a choice of operating systems, at this time you could type in the label for whichever operating system you want to boot.

If LILO is booting Linux, it first loads the kernel into memory, which is a vmlinuz file (plus a version number, for example, vmlinuz-2.4.0-xx) located in the /boot directory. Then the kernel passes control to init.

At this point, with the kernel loaded into memory and operational, Linux is already started, although at a very basic level. However, with no applications utilizing the kernel and with no ability for the user to provide meaningful input to the system, not much can be done with it. The init program solves this problem by bringing up the various services that allow the system to perform its particular role.

Init

The kernel finds init in /sbin and executes it, and init which coordinates the rest of the boot process.

When init starts, it becomes the parent or grandparent of all of the processes that start up automatically on your Red Hat Linux system. First, it runs the /etc/rc.d/rc.sysinit script, which sets your path, starts swapping, checks the filesystems, and so on. Basically, rc.sysinit takes care of everything that your system needs to have done at system initialization. For example, on a networked system, rc.sysinit uses the information in the /etc/sysconfig/network file to initialize network processes. Most systems use a clock, so on them rc.sysinit uses the /etc/sysconfig/clock file to initialize the clock. If you have special serial port processes that need to be initialized, rc.sysinit may also run rc.serial.

Then, init runs the /etc/inittab script, which describes how the system should be set up in each runlevel and sets the default runlevel. (See the section called Init Runlevels for more information on init runlevels.) This file states, among other things, that /sbin/update should be run whenever a runlevel starts. The update program is used to flush dirty buffers back to disk.

Whenever the runlevel changes, init uses the scripts in /etc/rc.d/init.d to start and stop various services, such as your web server, DNS server, and so on. First, init sets the source function library for the system (commonly /etc/rc.d/init.d/functions), which spells out how to start or kill a program and how to find out the PID of a program. Then, init determines the current and the previous runlevel.

Next, init starts all of the background processes necessary for the system to run by looking in the appropriate rc directory for that runlevel (/etc/rc.d/rc<x>.d, where the <x> is numbered 0-6). init runs each of the kill scripts (their file name starts with a K) with a stop parameter. Then, init runs all of the start scripts (their file names start with an S) in the appropriate runlevel directory with a start so that all services and applications are started correctly. In fact, you can execute these same scripts manually after the system is finished booting with a command like /etc/rc.d/init.d/httpd stop or service httpd stop logged in as root. This will stop the httpd server.

NoteNote
 

When starting services manually, you should be root. If you get a error when executing service httpd stop, you may not have /sbin pathed in /root/.bashrc (or the correct .rc file for your preferred shell). You can either type the full command of /sbin/service httpd stop or add export PATH="$PATH:/sbin" to your shell .rc file. If you edit your shell configuration file, log out and back in as root to make the changed shell configuration file take effect.

None of the scripts that actually start and stop the services are located in /etc/rc.d/rc<x>.d. Rather, all of the files in /etc/rc.d/rc<x>.d are symbolic links that point to actual scripts located in /etc/rc.d/init.d. A symbolic link is nothing more than a file that simply points to another file, and they are used in this case because they can be created and deleted without affecting the actual script that kills or starts the service. The symbolic links to the various scripts are numbered in a particular order so that they start in that order. You can change the order in which the services start up or are killed by changing the name of the symbolic link that refers to the script that actually starts or kills the service. You can give symbolic links the same number as other symbolic links if you want that service start or stop right before or after another service.

For example, for runlevel 5, init looks into the /etc/rc.d/rc5.d directory and might finds the following (your system and configuration may vary):

K01pppoe -> ../init.d/pppoe
K05innd -> ../init.d/innd
K10ntpd -> ../init.d/ntpd
K15httpd -> ../init.d/httpd
K15mysqld -> ../init.d/mysqld
K15pvmd -> ../init.d/pvmd
K16rarpd -> ../init.d/rarpd
K20bootparamd -> ../init.d/bootparamd
K20nfs -> ../init.d/nfs
K20rstatd -> ../init.d/rstatd
K20rusersd -> ../init.d/rusersd
K20rwalld -> ../init.d/rwalld
K20rwhod -> ../init.d/rwhod
K25squid -> ../init.d/squid
K28amd -> ../init.d/amd
K30mcserv -> ../init.d/mcserv
K34yppasswdd -> ../init.d/yppasswdd
K35dhcpd -> ../init.d/dhcpd
K35smb -> ../init.d/smb
K35vncserver -> ../init.d/vncserver
K45arpwatch -> ../init.d/arpwatch
K45named -> ../init.d/named
K50snmpd -> ../init.d/snmpd
K54pxe -> ../init.d/pxe
K55routed -> ../init.d/routed
K60mars-nwe -> ../init.d/mars-nwe
K61ldap -> ../init.d/ldap
K65kadmin -> ../init.d/kadmin
K65kprop -> ../init.d/kprop
K65krb524 -> ../init.d/krb524
K65krb5kdc -> ../init.d/krb5kdc
K75gated -> ../init.d/gated
K80nscd -> ../init.d/nscd
K84ypserv -> ../init.d/ypserv
K90ups -> ../init.d/ups
K96irda -> ../init.d/irda
S05kudzu -> ../init.d/kudzu
S06reconfig -> ../init.d/reconfig
S08ipchains -> ../init.d/ipchains
S10network -> ../init.d/network
S12syslog -> ../init.d/syslog
S13portmap -> ../init.d/portmap
S14nfslock -> ../init.d/nfslock
S18autofs -> ../init.d/autofs
S20random -> ../init.d/random
S25netfs -> ../init.d/netfs
S26apmd -> ../init.d/apmd
S35identd -> ../init.d/identd
S40atd -> ../init.d/atd
S45pcmcia -> ../init.d/pcmcia
S55sshd -> ../init.d/sshd
S56rawdevices -> ../init.d/rawdevices
S56xinetd -> ../init.d/xinetd
S60lpd -> ../init.d/lpd
S75keytable -> ../init.d/keytable
S80isdn -> ../init.d/isdn
S80sendmail -> ../init.d/sendmail
S85gpm -> ../init.d/gpm
S90canna -> ../init.d/canna
S90crond -> ../init.d/crond
S90FreeWnn -> ../init.d/FreeWnn
S90xfs -> ../init.d/xfs
S95anacron -> ../init.d/anacron
S97rhnsd -> ../init.d/rhnsd
S99linuxconf -> ../init.d/linuxconf
S99local -> ../rc.local

These symbolic links tell init that it needs to kill pppoe, innd, ntpd, httpd, mysqld, pvmd, rarpd, bootparamd, nfs, rstatd, rusersd, rwalld, rwhod, squid, amd, mcserv, yppasswdd, dhcpd, smb, vncserver, arpwatch, named, snmpd, pxe, routed, mars-nwe, ldap, kadmin, kprop, krb524, krb5kdc, gated, nscd, ypserv, ups, and irda. After all processes are killed, init looks into the same directory and finds start scripts for kudzu, reconfig, ipchains, portmap, nfslock, autofs, random, netfs, apmd, identd, atd, pcmcia, sshd, rawdevices, xinetd, lpd, keytable, isdn, sendmail, gpm, canna, crond, FreeWnn, xfs, anacron, rhnsd, and linuxconf. The last thing init does is run /etc/rc.d/rc.local to run any special scripts configured for that host. At this point, the system is considered to be operating at runlevel 5.

After init has progressed through all of the runlevels, the /etc/inittab script forks a getty process for each virtual console (login prompts) for each runlevel (runlevels 2-5 get all six; runlevel 1, which is single user mode, only gets one console; runlevels 0 and 6 get no virtual consoles). Basically, getty opens tty lines, sets their modes, prints the login prompt, gets the user's name, and then initiates a login process for that user. This allows users to authenticate themselves to the system and begin to use it.

Also, /etc/inittab tells init how it should handle a user hitting [Ctrl]-[Alt]-[Delete] at the console. As Red Hat Linux should be properly shut down and restarted rather immediately power-cycled, init is told to execute the command /sbin/shutdown -t3 -r now when a user hits those keys. In addition, /etc/inittab states what init should do in case of power failures, if your system has a UPS unit attached to it.

In runlevel 5, /etc/inittab runs a script called /etc/X11/prefdm. The prefdm script runs the preferred X display manager (gdm if you're running GNOME, kdm if you're running KDE, or xdm if you're running AnotherLevel) based on the contents of the /etc/sysconfig/desktop directory.

At this point, you should be looking at a login prompt. All that, and it only took a few seconds.

SysV Init

As we have seen, the init program is run by the kernel at boot time. It is in charge of starting all the normal processes that need to start up with the system. These include the getty processes that allow you to log in, NFS daemons, FTP daemons, and anything else you want to run when your machine boots.

SysV init is the standard init process in the Linux world to control the startup of software at boot time, because it is easier to use and more powerful and flexible than the traditional BSD init.

SysV init also differs from BSD init in that the configuration files are in /etc/rc.d instead of residing directly in /etc. In /etc/rc.d, you will find rc, rc.local, rc.sysinit, and the following directories:

init.d
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d

SysV init represents each of the init runlevels with a separate directory, using init and symbolic links in each of the directories to actually stop and start the services as the system moves from runlevel to runlevel.

In summary, the chain of events for a SysV init boot is as follows:

The default runlevel is decided in /etc/inittab. You should have a line close to the top like:

id:3:initdefault:

The default runlevel is 3 in this example, the number after the first colon. If you want to change it, you can edit /etc/inittab by hand. Be very careful when you are editing the inittab file. If you do mess up, you can fix it by rebooting, accessing the boot: prompt with [Cntl]-[X], and typing:

boot:  linux single

This should allow you to boot into single-user mode so you can re-edit inittab to its previous value.

Next, we'll discuss information in the files within /etc/sysconfig that define the parameters used by different system services when they start up.