Linux Boot Process

Linux Boot Process


This post was last updated on June 3rd, 2020 at 03:34 pm

The following is from /usr/src/linux-2.4/Documentation/initrd.txt

When using initrd, the system typically boots as follows:

1) the boot loader loads the kernel and the initial RAM disk
2) the kernel converts initrd into a “normal” RAM disk and
frees the memory used by initrd
3) initrd is mounted read-write as root
4) /linuxrc is executed (this can be any valid executable, including
shell scripts; it is run with uid 0 and can do basically everything
init can do)
5) linuxrc mounts the “real” root file system
6) linuxrc places the root file system at the root directory using the
pivot_root system call
7) the usual boot sequence (e.g. invocation of /sbin/init) is performed
on the root file system
8) the initrd file system is removed

On Red Hat 7.2, the initrd /linuxrc usually contains something similar to
the following (This system is running ext3 and a Compaq Array Controller):


echo "Loading scsi_mod module"
insmod /lib/scsi_mod.o 
echo "Loading sd_mod module"
insmod /lib/sd_mod.o 
echo "Loading cpqarray module"
insmod /lib/cpqarray.o 
echo "Loading jbd module"
insmod /lib/jbd.o 
echo "Loading ext3 module"
insmod /lib/ext3.o 
mount -t proc /proc /proc
echo Mounting /proc filesystem
echo Creating root device
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
umount /proc
echo Mounting root filesystem
mount --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd

As you can see it loads the necessary SCSI drivers to access the filesystem
(remember that until the filesystem drivers are loaded, you only have access
to the initrd and vmlinuz). After the SCSI drivers you see the filesystem
drivers loaded (ext3). Then it takes care of some maintenance tasks: set
up /proc, sets the root device, transfers control to the root device.

Here is a listing of the files on this same initrd image:

.:			directory
./lib:			directory
./lib/scsi_mod.o:	ELF 32-bit LSB relocatable, Intel 80386, version 1, not stripped
./lib/sd_mod.o:		ELF 32-bit LSB relocatable, Intel 80386, version 1, not stripped
./lib/cpqarray.o:	ELF 32-bit LSB relocatable, Intel 80386, version 1, not stripped
./lib/jbd.o:		ELF 32-bit LSB relocatable, Intel 80386, version 1, not stripped
./lib/ext3.o:		ELF 32-bit LSB relocatable, Intel 80386, version 1, not stripped
./bin:			directory
./bin/nash:		ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, stripped
./bin/insmod:		ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, stripped
./sbin:			directory
./sbin/bin:		broken symbolic link to bin
./sbin/modprobe:	broken symbolic link to /bin/nash
./etc:			directory
./dev:			directory
./dev/console:		character special (5/1)
./dev/null:		character special (1/3)
./dev/ram:		block special (1/1)
./dev/systty:		character special (4/0)
./dev/tty1:		character special (4/1)
./dev/tty2:		character special (4/2)
./dev/tty3:		character special (4/3)
./dev/tty4:		character special (4/4)
./loopfs:		directory
./proc:			directory
./sysroot:		directory
./linuxrc:		a /bin/nash script text executable

Next it appears that /sbin/init is called.

/sbin/init performs the activities described in its configuration file, /etc/inittab:


# inittab       This file describes how the INIT process should set up
#               the system in a certain run-level.
# Author:       Miquel van Smoorenburg, 
#               Modified for RHS Linux by Marc Ewing and Donnie Barnes

# Default runlevel. The runlevels used by RHS are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)

# System initialization.

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6

# Things to run in every runlevel.

ca::ctrlaltdel:/sbin/shutdown -t3 -r now

# When our UPS tells us power has failed, assume we have a few minutes
# of power left.  Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.  
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"

# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"

# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty 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

# Run xdm in runlevel 5
# xdm is now a separate service
x:5:respawn:/etc/X11/prefdm -nodaemon

Here is an explanation of the above inittab sample:
The first field us just a descriptor – keep these unique
The 2nd field is which runlevel(s) does this entry apply to
The 3rd field seems to be some specific keyword that /sbin/init understands such
as wait, respawn, once, ctrlaltdel, powerfail, powerokwait, initdefault, etc.
The 4th fied seems to be the program/script that is to be called along with any parameters.

One of the items in /etc/inittab is as follows:


This line calls /etc/rc.d/rc.sysinit.

Also note that any “wait” lines will wait until the system has booted before they start.

Here is the short summary of what rc.sysinit does
system logs
date and time
system font
swap partitions
file system checks
mount the filesystems read/write

Here are some of the flags that rc.sysinit keeps track of

Here is a more lengthy description on some of what rc.sysinit does as it brings up the system:

# Fix console loglevel
# Mount /proc (done here so volume labels can work with fsck)
# Unmount the initrd, if necessary
# Configure kernel parameters
# Set the system clock.
# Start up swapping.
# Set the hostname.
# Initialize USB controller and HID devices
# Possibly update quotas if fsck was run on /.
# check for arguments passed from kernel
# set up pnp
# Remount the root filesystem read-write.
# LVM initialization
# Clear mtab
# Remove stale backups
# Enter root, /proc and (potentially) /proc/bus/usb and devfs into mtab.
# Turn on harddisk optimization
# The root filesystem is now read-write, so we can now log via syslog() directly..
# tweak isapnp settings if needed.
# Load sound modules iff they need persistent DMA buffers
# Load modules (for backward compatibility with VARs)
# Add raid devices
# Check filesystems
# Mount all other filesystems (except for NFS and /proc, which is already
# mounted). Contrary to standard usage,
# filesystems are NOT unmounted in single user mode.
# check remaining quotas other than root
# Turn on process accounting
# Configure machine if necessary.
# Clean out /etc.
# Do we need (w|u)tmpx files? We don’t set them up, but the sysadmin might…
# Clean up /var
# I’d use find, but /usr may not be mounted.
# Reset pam_console permissions
# Clean up utmp/wtmp
# Delete X locks
# Delete Postgres sockets
# Now turn on swap in case we swap to files.
# Initialize the serial ports.
# If a SCSI tape has been detected, load the st module unconditionally
# since many SCSI tapes don’t deal well with st being loaded and unloaded
# Load usb storage here, to match most other things
# If they asked for ide-scsi, load it
# Generate a header that defines the boot kernel.
# Adjust symlinks as necessary in /boot to keep system services from
# spewing messages about mismatched System maps and so on.
# Now that we have all of our basic modules loaded and the kernel going,
# let’s dump the syslog ring somewhere so we can find it later
# Also keep kernel symbols around in case we need them for debugging
# create the crash indicator flag to warn on crashes, offer fsck with timeout

After /sbin/init finishes with /etc/rc.d/rc.sysinit (which was specified by the
“sysinit” line), it then switches to the default runlevel (which is defined by
the “initdefault” line in /etc/inittab).

Changing runlevels should leave any processes running that are in both the old
and new runlelves.

More info by running man on the following entries:
init, telinit, inittab, runlevel

When init starts scripts in the runlevel it does the “start” scripts from
0 to 99. Red Hat 7.2 places a S99local in runlevels 2, 3, 4, and 5, which
points to /etc/rc.d/rc.local.

You can control what starts and stops in each runlevel using the following commands:

chkconfig --list myservice              # Checks the startup status of "myservice"
chkconfig --level 2345 myservice on     # Start "myservice" when entering runlevels 2, 3, 4, & 5
chkconfig --level 2345 myservice off    # Stop "myservice" when entering runlevels 2, 3, 4, & 5
ksysv     # Another runlevel editor
ntsysv    # Another runlevel editor

Note: The services you can control with chkconfig are listed in /etc/rc.d/init.d/

So, to start the web server, for example, you would make sure it will be started on each boot:

chkconfig --level 2345 httpd start

Then to start it you would either reboot or type one of the following two commands:

service httpd start
/etc/rc.d/init.d/httpd start

Note: The above two commands are basically the same. “service” basically provides a
link to the /etc/rc.d/init.d/ directory. The only difference is that service does
some sort of checks before actually runnint /etc/rc.d/init.d/yourservice.

One of the services that generally starts on a Red Hat Linux system is xinetd.
Xinetd has its own startup scripts in /etc/xinetd.d/. Xinetd generally handles
the following services by default: talk, ftp, rsh, pop3, imap, etc. To start a
service controlled by xinetd, you edit the appropriate script in /etc/inetd.d/ to
turn that service on, then run “service xinetd reload” to allow xinetd to recheck
those startup scripts. Then when the client attempts to connect to the service,
xinetd starts the appropriate server service. Note that if you are starting the
ftp service this way, the ftp server won’t actually be running until a client
attempts to connect.

So to summarize
HW init
if no GRUB/LILO on MBR, then find GRUB/LILO on BOOT Sector of active primary partition.
GRUB/LILO/or BOOT Loader loads initrd, then vmlinuz.
initrd loads necessary scsi drivers and filesystem drivers.
initrd then mounts the real root device as root and passes control to /sbin/init
/sbin/init reads config info from /etc/inittab
/etc/inittab runs /etc/rc.d/rc.sysinit
After rc.sysinit finishes, /sbin/init (because of inittab) then moves into the
default runlevel specified which runs all of the “start” scripts for that runlevel –
including rc.local which is the last start script in runlevels 2, 3, 4, and 5.
After all this then the login prompts are displayed.

Probably the next course in this should be to explain how the login environment is set up:
paths, /etc/profile, ~/.bashrc ~/.bash_profile, etc.

prev next index

Previous How to Modify Red Hat Boot Disks and Driver Disks
Next Setting Routes in Linux

About author

Sibananda Sahu
Sibananda Sahu 186 posts

A Linux Kernel Developer and a Firmware Developer by profession. Have worked with few big companies: BROADCOM Corporation, Cypress Semiconductor, LSI Corporation, TOSHIBA Corporation, Western Digital; on various cutting edge technologies and product lines, such as: RAID storage Driver, SSD Firmware, WLAN Firmware etc. Having more than 9 years of experience in Software Engineering domain. Now, took a pledge to educate all aspirant students to teach about Linux Kernel Development.

View all posts by this author →

You might also like

System Understanding 0 Comments

The Differences Between UEFI And BIOS

BIOS and UEFI both are the firmware interfaces that act as an interpreter between the system’s firmware and operating system. A firmware interface initializes the hardware components while the startup

System Understanding 0 Comments

Understanding and Working with the MBR

This post was last updated on May 26th, 2020 at 09:50 pmStandard MBR functionality can be restored by adding proper boot code back into the MBR. This document will mostly

System Understanding 0 Comments

Linux Loop Devices

This post was last updated on June 1st, 2020 at 07:00 pmBy default you have 8 loop devices (loop0 – loop7). You can extend this number up to 255 (maybe


No Comments Yet!

You can be first to comment this post!

Leave a Reply