Skip to main content

Ralsina.Me — Roberto Alsina's website

The Linux Booting Process Unveiled

Biblical version:

In the be­gin­ning, there was GRUB (or maybe LILO) and GRUB load­ed the ker­nel, and ker­nel be­gat init, and init be­gat rc, and rc be­gat net­work and httpd and get­ty, and get­ty be­gat login, and lo­gin be­gat shell and so on.

Introduction

In this ar­ti­cle we will ex­plore how most Lin­ux dis­tri­bu­tions boot, in some de­tail. I haven't seem many full ex­pla­na­tions of this, and it's not ter­ri­bly com­plex, al­though it is some­what long.

I will use a Red Hat 9 sys­tem to ex­plain it, but most dis­tri­bu­tions should be al­most the same... ex­cept Slack­ware and its de­riv­a­tives.

While al­most ev­ery­one us­es what's called a Sys­temV init se­tup, Slack­ware and de­riv­a­tives use a BSD init ( like FreeB­S­D, Open­BSD and *B­S­D, of course :-), which is dif­fer­en­t.

Step 1: The Boot Manager

The boot man­ag­er is a small pro­gram that re­sides most­ly on the MBR [1] and presents you with a menu let­ting you choose what op­er­at­ing sys­tem (if you have more than one) you want to boot.

Nowa­days the most com­mon one is GRUB, with LILO a sec­ond pop­u­lar al­ter­na­tive. [2]

I will not get in­to much de­tail about them, both are well doc­u­ment­ed, and most of what you want to know about them is how to make them boot win­dows, or mul­ti­ple lin­ux ker­nel­s, and that's not what this ar­ti­cle is about.

In the reg­u­lar, plain-old-­boot­ing-lin­ux busi­ness, all the boot load­er does is:

  • Load the ker­nel in­to mem­o­ry
  • Op­tion­al­ly load a ramdisk called ini­trd con­tain­ing stuff like disk driv­ers
  • Pass the ker­nel ar­gu­ments, of which we are on­ly in­ter­est­ed in run­lev­el and init
  • Start ex­e­cu­tion of the ker­nel.

So, what are those two ar­gu­ments I men­tioned, run­lev­el and init? We'll get to run­lev­el even­tu­al­ly, but init we'll see soon.

Step 2: init

The init ar­gu­ment the boot load­er can pass to the ker­nel is the name of a pro­gram. Usu­al­ly, none is given, and the de­fault, /s­bin/init is used.

You could, for ex­am­ple, pass init=/bin/sh to the ker­nel, and then a plain shell would be used in­stead.

What does the ker­nel do with init? It starts it. It's the on­ly pro­gram the ker­nel it­self start­s, ev­ery­thing else is start­ed by init.

The reg­u­lar Lin­ux init will then read a file called /etc/init­tab to see what it has to do. The for­mat of that file is some­what in­volved and ar­chaic, but it's not too com­plex.

To un­der­stand it, you have to know what a run­lev­el is. A run­lev­el is a state for the sys­tem. Usu­al­ly, you have run­levels 0,1,2,3,4,5,6 and maybe S (De­bian has it, Red Hat does­n't).

For ex­am­ple, run­lev­el 1 (or S) usu­al­ly means a sin­gle shell run­ning, as few pro­cess­es as pos­si­ble, maybe no login, maybe just ask­ing for root's pass­word. While run­lev­el 5 may mean 6 lo­gins in text mod­e, a graph­i­cal login, and a web serv­er run­ning. As I said, two dif­fer­ent states of the sys­tem.

The sys­tem start­s, when init loads in an un­de­fined state (some­times called N), and then will switch to one run­lev­el or an­oth­er de­pend­ing on what the run­lev­el ar­gu­ment from the boot­load­er to the ker­nel was, and the con­tents of /etc/init­tab.

For ex­am­ple, if the boot­load­er passed run­lev­el as 5, init will try to switch to that state. If no run­lev­el ar­gu­ment was passed, it will use its de­fault, which is in /etc/init­tab

Nor­mal­ly the on­ly rea­son for the boot­load­er to pass an ar­gu­ment is if you want it to boot in an un­usu­al state, for ex­am­ple, a sin­gle-us­er mode for main­te­nance (run­lev­el 1), or with a re­place­ment init be­cause of disk cor­rup­tion (init=/bin/sh).

So, let's look at that file...

Step 2.1: /etc/inittab

All lines start­ing with # are com­ments

The oth­er lines are like this:

1:2345:respawn:/sbin/mingetty tty1

They have 4 field­s, sep­a­rat­ed with colon­s, which mean (tak­en from the init­tab(5) man page).

id
This has no real meaning, but should be different for each line, can be one to four characters
runlevels
For example, 2345 means this line applies to runlevels 2,3,4 and 5. In some actions (see below) this field is ignored, in some it means something else :-P
action
what this line does
process
a command to be executed. Some actions require no command

When it's boot­ing, to de­cide the de­sired run­lev­el (a­gain, if it's not passed as an ar­gu­men­t), init will look for a line with the init­de­­fault ac­tion.

For ex­am­ple:

id:5:initdefault:

That mean­s: go to run­lev­el 5. So, if you want­ed to change the de­fault run­level, that's what you change.

But what does it mean to go to one run­level? Well, each run­lev­el runs a dif­fer­ent con­fig­u­ra­tion of soft­ware. One run­lev­el may have a web­serv­er run­ning, and an­oth­er not have it. One run­lev­el may show you a graph­i­cal lo­gin screen, or not, or give you 6 text ter­mi­nal­s, or one.

Think of it like those old multi­boot menus on DOS which read dif­fer­ent au­­toex­ec.­­bat and con­­fig.sys files.

The mean­ing of the run­levels may be dif­fer­ent on dif­fer­ent dis­tri­bu­tion­s, here's what it says for Red Hat:

# 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)

So, for ex­am­ple, if you switched to run­lev­el 6, it would re­boot. You can switch run­levels at any mo­ment us­ing the telin­it com­mand, but for the pur­pos­es of boot­ing and this ar­ti­cle, you switch on­ly on­ce, to the de­fault run­level, and you're done.

So, what hap­pens af­ter you know you are go­ing to run­lev­el 5?

If you are boot­ing, you check all lines with ac­tions sysinit boot and boot­wait, in that or­der, and run what the com­mand field says.

In Red Hat's de­fault init­tab, that's just this:

si::sysinit:/etc/rc.d/rc.sysinit

So, it will run a script called /etc/r­c.d/r­c.sysinit, which does stuff like load­ing a ter­mi­nal font, check disks, mount stuff... ba­sic sys­tem hab­it­abil­i­ty drudge work.

Then it will get all lines with ac­tion once and wait that have the de­sired run­lev­el in the run­lev­el field, and will run its com­mand­s, and will wait un­til the wait lines com­mands are fin­ished.

In Red Hat, for run­lev­el 5:

l5:5:wait:/etc/rc.d/rc 5

What this par­tic­u­lar script does is start all ser­vices con­fig­ured for run­lev­el 5. That's what you see when it says things like "con­fig­ur­ing the frob­nozz [OK]" on boot. Now, let's see the de­tail­s...

Step 3: Services

In fac­t, ser­vices start be­fore the end of what's de­scribed in Step 2.1, so this is no longer log­i­cal­ly or­ga­nized. Com­plain to Con­gress, not to me ;-)

When you in­stall a de­cent­ly pack­aged soft­ware that needs to run with­out be­ing man­u­al­ly start­ed by a us­er (think web­server), it should have pro­vid­ed you with a con­trol script for it­self, and placed it in the stan­dard place: /etc/init.d/ or /etc/r­c.d/init.d de­pend­ing on dis­tri­bu­tion. Most have both and they are the same.

There you will find many script­s. For ex­am­ple, I have one called /etc/init.d/net­­work which, amaz­ing­ly enough, con­trols the net­work.

For ex­am­ple, if I do /etc/init.d/net­­work stop [3] it brings down the net­work. If I did /etc/init.d/net­­work start it would bring it back up.

Some ser­vices sup­port more or less com­mand­s, but all sup­port stop, start and restart. You can learn what they han­dle by call­ing it with­out ar­gu­ments:

[root@roberto root]# /etc/init.d/network
Usage: /etc/init.d/network {start|stop|restart|reload|status}
[root@roberto root]# /etc/init.d/httpd
Usage: /etc/init.d/httpd {start|stop|restart|condrestart|reload|status|fullstatus|graceful|
help|configtest}

For each run­level, there's a list of ser­vices that should be start­ed, and a list of ser­vices that should be stopped.

On en­ter­ing run­lev­el 5, for ex­am­ple, you may want to stop ser­vice httpd but start ser­vice smb, or what­ev­er.

I heav­i­ly rec­om­mend you use a sys­tem man­age­ment tool, like Red Hat's red­hat-­­con­­fig-ser­vices or De­bian's rc­­conf to han­dle this, they are sim­ple and work just fine.

But, if you want to do it by hand, or just want to know how that con­fig­u­ra­tion is stored, read on :-)

For each run­lev­el N, there is a fold­er, called /etc/r­c.d/r­c­N.d.

Here's part of my fold­er for run­lev­el 5:

K05saslauthd -> ../init.d/saslauthd
K10lircd -> ../init.d/lircd
K10lircmd -> ../init.d/lircmd
K15httpd -> ../init.d/httpd
K15nessusd -> ../init.d/nessusd
:
:
:
S00microcode_ctl -> ../init.d/microcode_ctl
S05kudzu -> ../init.d/kudzu
S08iptables -> ../init.d/iptables
S10network -> ../init.d/network
S12syslog -> ../init.d/syslog
S13irqbalance -> ../init.d/irqbalance
:
:
:

The things that start with K are to be stopped. Those which start with S are to be start­ed. The num­bers are to give them an or­der to be killed or start­ed.

So, we start by tak­ing all the K stuff. For each, we check if the ser­vice is run­ning. If it is, it's stopped.

Then we go over all the S stuff, if it is not run­ning, it's start­ed.

The stop­ping or start­ing is sim­ply done by call­ing, for ex­am­ple

/etc/rc.d/rc5.d/S10network start

Since S10net­­work is a sym­bol­ic link to /etc/r­c.d/init.d/net­­work, it's just the same as what we used be­fore to start the net­work ser­vice.

In Red Hat, there's one par­tic­u­lar ser­vice called lo­­cal, usu­al­ly start­ed in last place (like S99lo­­cal), which runs /etc/r­c.d/r­c.lo­­cal.

If you have some­thing you want to run on boot, but don't want to both­er cre­at­ing a ser­vice script (or don't know how), you can just tack it on the end in rc.lo­­cal and have it work.

How­ev­er, be care­ful! You can't lo­gin in­to the sys­tem [4] un­til rc.l­coal fin­ish­es, so don't put there any com­mands that take too long. Or if you do, put them in the back­ground by adding a & at the end of the com­mand.

On oth­er dis­tri­bu­tions this will be dif­fer­en­t. For ex­am­ple, De­bian has a fold­er where you throw script­s, in­stead of a sin­gle file.

Af­ter all that is done, all ser­vices are start­ed, we get back to init­tab.

Step 4: More inittab fun

Now init will get all lines with ac­tion respawn for the de­sired run­lev­el and start their pro­cess­es. respawn com­mands are restart­ed when they end, so they will be run­ning pret­ty much all the time as long as you are in this run­lev­el. [5]

In Red Hat for run­lev­el 5:

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
x:5:respawn:/etc/X11/prefdm -nodaemon

The lines with id 1 through 6 run a pro­gram in the ter­mi­nals you reach us­ing AL­T-F1 through AL­T-F6, which asks your user­name. Yes, those are what you use to lo­gin in text mod­e.

The line with id x gives you a graph­i­cal lo­gin. No­tice that this is not in run­levels 1,2,3 or 4, so those have no graph­i­cal lo­gin.

You could have more or less text ter­mi­nals or graph­ic lo­gins edit­ing this. No­tice that to have two graph­i­cal lo­gins you need oth­er con­fig­u­ra­tions, too.

And voilá, you are boot­ed and ready to lo­gin.


[1] Master boot Record, a small piece at the beginning of your disk.
[2] LILO has some limitations, but it's simpler. However, GRUB is both more powerful and easier to fix when in trouble.
[3] I have to use the full path to execute it because it's not in one of the regular directories where programs are stored. Some distros, including Red Hat, include a handy command called ser­vice that lets you do this instead: ser­vice net­work stop with the same effect.
[4] At least locally, you may enter through ssh if the service is up
[5] Other pieces of inittab inclulde what should happen when you press ctr-alt-delete (ctr­lalt­del action) or how to react to power failure to your UPS (powerok, pow­er­wait, pow­er­fail) or have functionality I have never seen in use (on­de­mand), but that's beyond the scope of this article.
Roberto Alsina / 2006-04-04 16:27:

Comments for this story are here:

http://www.haloscan.com/com...

Fabian / 2006-11-10 02:48:

Dear Mr. Roberto Alsina,
You're english is quate unadecuate, yoou read like an indian! Just in case you need a helping hand, give an (electronic) call.
Yours truly,
moviconvers.

Roberto Alsina / 2010-10-05 18:32:

To whoever flagged the comment: don't bother.

I am not into censoring morons who complain about my english while ignoring the diference between "you're" and "your". Besides, this is three years old, people! ;-)

Roberto Alsina / 2006-11-10 11:09:

Fabian: I am surprised someone can be such a fucking moron to leave that comment.

employment background check / 2011-12-27 23:23:


Hi very nice article