17. HET OPSTART-PROCES
Het BIOS
Het duurt altijd even voor je met een computer kunt werken nadat je hem hebt
ingeschakeld. Dit artikel gaat over wat er allemaal gebeurt in die tijd.
Als je de computer inschakelt wordt eerst een programma gedraaid, dat zich
vast, ongeacht het besturingssysteem, in je computer bevindt. Het zit in zgn.
ROM-geheugen (read-only memory). Dit programma wordt het BIOS
genoemd (Basic Input/Output System). Het controleert of de hardware van
je computer in orde is. Je kunt dit programma een beetje beinvloeden d.m.v.
de BIOS-instellingen. Die instellingen vind je als je op de
del-toets drukt vlak na het inschakelen (bij sommige computers kan
dat ook een andere toets zijn, zoals F1). Meestal kun je dat tijdens het opstarten
zien op je scherm, bv.: Press del to enter setup....
In die setup kun je bv. aangeven waar (en in welke volgorde) dat programma
eerst moet zoeken naar een zgn. boot-sector: op de flop, op de harde schijf
of op de CD-Rom. Daarnaast kan er aan nog heel wat andere instellingen
gesleuteld worden, maar dat is vaak werk voor specialisten. Ik zou een
beginner niet aanraden daar mee te gaan spelen!
Boot-sector
Na de controle van de hardware zal het BIOS-programma de bootsector lezen (op
de schijf, die aangegeven is in de setup-gegevens). Die bootsector is altijd
het eerste gedeelte (de eerste sector) van die schijf. Het BIOS-programma
herkent een bootsector o.a. aan de inhoud van de laatste 2 bytes van die
secor. Die bevatten een zgn. magic number, met een waarde van AA55
(hexadecimaal) oftewel 43603 (decimaal). Een bootsector is trouwens altijd
precies 512 bytes groot.
Als de bootsector gevonden is, wordt deze in het geheugen geladen. De
bootsector bevat een programma, een zgn boot-loader (voor Linux vaak LILO of
GRUB), dat zorgt dat het eigenlijke besturingssyteem (in ons geval: de Linux
kernel) geladen wordt.
De kernel
Zodra de kernel in het geheugen geladen is, neemt die het heft in handen. De
Linux kernel maakt nauwelijks gebruik van de hardware-gegevens van het BIOS,
maar regelt op eigen wijze alles zèlf. En dat doet hij goed en
efficiënt!
Nu bestaan er meerdere mogelijkheden voor de verdere voortgang van het
opstartproces. De door de meeste distributies gebruikte weg is die via
initrd, zodat we die hier zullen beschrijven. Deze manier wordt wel
de "two-phased system boot-up" genoemd. Het kan echter ook zonder deze
tussenstap, dus een "one-phased system boot-up". Voor dat laatste geval kun
je het hele verhaal over initrd overslaan.
Initrd
Initrd is een speciaal bestand, dat zich normaal gesproken bevindt op
/dev/initrd. Het doet zich dus voor als een device, en wel een
block-device. Dit bestand wordt door de bootloader al geladen
vóór de kernel gestart wordt. De kernel kan dus direct gebruik
maken van dit block-device. Initrd wordt geladen in het geheugen,
en daarna uitgepakt naar een zgn. RAM-disk: een stukje geheugen, dat door de
kernel benaderd wordt als was het een (harde) schijf.
Het uitgepakte bestand initrd bevat een zgn. root-bestandssysteem
(dus alle benodigde Linux-directorie en een aantal bestanden en programma's).
De kernel mount dit bestandssyteem (/dev/ram0) bij het
opstarten en voert een in dat bestandssysteem opgenomen programma
/linuxrc uit, dat bv. zorgt voor het laden van de later benodigde
drivers en modules (een module is eigenlijk een stukje kernel, dat als apart
onderdeel ervan na de eigenlijke kernel alsnog geladen kan worden).
Even op een rijtje: als de computer opstart met initrd, dan gebeurt
het volgende:
- De boot-loader laadt de kernel en de inhoud van /dev/initrd in
het geheugen.
- Als de kernel opstart, zal deze de inhoud van /dev/initrd
uitpakken (het is nl. een gecomprimeerd bestandssyteem) en kopiëren
naar /dev/ram0 en het geheugen, dat werd ingenomen door
/dev/initrd weer vrijgeven.
- De kernel mount /dev/ram0 als een (tijdelijk) root
bestandssysteem.
- Als in dit bestandssysteem het bestand /linuxrc gevonden wordt,
zal dit worden uitgevoerd. /linuxrc kan een gewoon programma of een
uitvoerbaar script zijn.
- Als /linuxrc klaar is met de uitvoering van zijn taken, zal het
"normale" root-bestandssysteem (wat zich meestal op de harde schijf bevindt)
gemount worden.
- Als het normale root-bestandssysteem een directory /initrd
bevat, zal /dev/ram0 daarop gemount worden. Als deze directory niet
bestaat, zal /dev/ram0 gewoon ge-unmount worden.
- Nu zal het "normale" opstart-proces weer uitgevoerd worden.
Enkele opmerkingen:
- De bootloader kan ook een ander bestand dan /dev/initrd laden
als tijdelijk root-bestandssyteem. Met Lilo wordt dat bv. aangegeven in
/etc/lilo.conf door een regel: initrd=bestandsnaam.
- De kernel weet waar hij het "normale" root-bestandssysteem kan vinden
doordat dat ingebakken zit in de kernel (met de rdev-opdracht, niet
iets voor beginners!), of ook weer door een vermelding in
/etc/lilo.conf: root=device-naam. Bij een vermelding van
root=/dev/ram0 wordt initdr beschouwd als "normaal"
root-bestandssysteem en blijft Linux dus in RAM-disk draaien.
Met of zonder initrd wordt in ieder geval alle nodige hardware
geïnitialiseerd, zoals de harde schijf (waar de kernel net vanaf
gelezen is). Als er geen gebruik gemaakt wordt van initrd, dan zal
de kernel zoeken naar een uitvoerbaar /linuxrc-bestand op het
"normale" root-bestandssysteem.
De eerste arbeid van een kernel kun je vaak (als je heel snel kunt lezen) volgen
op het scherm: dat zijn die teksten, die vliegensvlug over je monitor rollen.
Je kunt ze gelukkig achteraf nog nalezen, want al die meldingen worden
opgeslagen in het bestand /var/log/messages.
Init
Eerst een opmerking vooraf: Pardus Linux heeft een geheel eigen Init-systeem, dat
afwijkt van het hieronder beschreven "oude" systeem. Dit nieuwe systeem zorgt er
o.a. voor, dat Pardus sneller opstart dan de meeste andere Linux-distributies.
Na dit alles wordt de besturing van het opstart-proces in handen gegeven van
het programma init. We gaan in dit verhaal trouwens uit van de
"System V"-stijl die de meeste Linux-distributies tegenwoordig gebruiken. Het
is echter mogelijk het init-proces anders in te richten.
Init wordt wel de moeder van alle processen genoemd. Alle processen
op een Linux-systeem hebben een nummer; init heeft altijd
procesnummer (PID) 1. Het init-programma is altijd te vinden in
/sbin/init.
Het init-proces wordt gestuurd door een configuratie-bestand
/etc/inittab. In dit bestand wordt o.a. aangegeven naar welk
runlevel doorgestart moet worden en, via weer andere scripts, welke
programma's daarvoor gestart moeten worden.
Runlevel
Een belangrijk concept van SysVinit wordt gevormd door het begrip runlevel.
Een runlevel beschrijft een bedrijfstoestand van een Unix/Linux-systeem. De
verschillende runlevels worden hieronder kort beschreven:
Runlevel |
Beschrijving |
0 |
Het systeem wordt uitgeschakeld. |
1 |
Single-user mode: alleen de "systeembeheerder" kan
met de computer werken. |
2 |
Het systeem draait beperkt, bv. er is geen netwerk
beschikbaar en geen grafische mode. |
3 |
Het systeem draait volledig. |
4 |
Dit runlevel kan naar eigen inzicht gebruikt
worden. |
5 |
Het systeem draait volledig. Of hiervoor runlevel 3
of 5 gebruikt wordt, hangt van de distributie af. Soms is 3 voor de
console-mode en 5 voor de grafische mode. |
6 |
Het systeem gaat rebooten (herstarten). |
/etc/inittab
Een voorbeeld van de inhoud van inittab vind je hieronder:
# Ingesteld runlevel bij het opstarten
id:3:initdefault:
# Voorbereiding
si::sysinit:/etc/rc.d/rc.sysinit
# De verschillende runlevels
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/tc.d/rc.6
# Wat is de vertaling van Ctrl-Alt-Del?
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# Login voor de console-mode
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
# Grafische login
x:5:respawn:/usr/X11R6/bin/xdm -nodeamon |
De regels die met een # beginnen zijn zgn. commentaar-regels; init
doet hier niets mee, maar ze zijn voor menselijke lezers handige
toelichtingen.
Iedere regel, die er wèl toe doet, bestaat steeds uit 4 delen, van elkaar
gescheiden door een dubbele punt (:).
Het eerste deel bestaat uit één of twee letters of cijfers, die
een soort afkorting vormen voor het doel van de betreffende regel
(si staat bv. voor sysinit en l2 voor level 2).
In het tweede deel kunnen getallen aangeven op welke runlevels de betreffende
regel betrekking heeft. Zo heeft de laatste regel alleen betrekking op
runlevel 5 en de regel met ca op alle runlevels (geen vermelding van
een getal betekent dus: alle runlevels).
Het derde deel wordt gevormd door een woord, waarmee aan init wordt
aangegeven hoe het met het in het vierde deel vermelde programma om moet gaan.
Zo betekent respawn dat het programma direct weer opgestart moet
worden, als het afgesloten wordt. Het mingetty-programma zorgt er bv.
voor dat de inlog-prompt verschijnt. Zodra een gebruiker uitlogt (bv. met de
opdracht exit), moet mingetty weer opgestart worden om een
eventuele volgende gebruiker de gelegenheid te geven in te loggen.
In tegenstelling hiermee kan ook het woord once gebruikt worden, om
aan te geven, dat het betreffende programma maar één keer
opgestart moet worden bij het bereiken van dat runlevel. Dat wordt bv. gedaan
bij programma's die zichzelf op de achtergrond zetten (zoals de zgn.
deamons).
Het woord wait wordt gebruikt in regels, die aangeven welke scripts
gedraaid moeten worden bij het veranderen van runlvel. Daar komen we zo op
terug.
Default runlevel
De regel in inittab met het woord initdefault geeft aan
naar welk runlevel bij het aanzetten van de computer automatisch doorgestart
wordt. Dit wordt aangegeven met het getal in het tweede deel van die
regel.
Dit kan handig zijn, als je bv. normaal gesproken doorstart naar de grafische
login (runlevel 5) en je je configuratie-bestand van de grafische schil
(X) "vernield" hebt, waardoor deze schil niet meer op kan starten.
Je kunt dan, na bv. opgestart te zijn met een rescue-flop of -CD, je initdefault
veranderen in 3 (console-mode), zodat je je computer toch weer "gewoon" op
kunt starten en je X-configuratie kunt repareren.
Sysinit
De regel met sysinit start een programma, dat alleen uitgevoerd
wordt bij het aanzetten van de computer, vóórdat naar een
runlevel doorgeschakeld wordt.
De taken, die door rc.sysinit worden uitgevoerd zijn bij de meeste
distributies de volgende:
- De systeemtijd wordt gelijkgezet met de hardware-klok.
- De harde schijf/schijven worden gecontroleerd op fouten en gemount.
Dit mounten wordt geregeld via /etc/fstab, maar daar gaan we hier
nu even niet op in.
- De swap-partitie wordt geactiveerd.
- Eventueel wordt een toetsenbord-driver geladen.
- Er wordt wat netwerk-functionaliteit voorbereid, zoals het vaststellen
van de naam van de computer.
- Tenslotte vinden er nog wat opruim-akties plaats.
Echter: één en ander is afhankelijk van met welke distributie
je werkt. Vooral oudere distributies beperken de akties van
rc.sysinit tot de klok, de computernaam en de controle van de harde
schijf.
Volgorde
Even samenvatten wat init allemaal doet:
- Eerst worden de opdrachten in het bestand rc.sysinit
uitgevoerd. Daarmee worden wat basisinstellingen geregeld.
- Daarna schakelt init door naar het door initdefault
aangegeven runlevel, waardoor allerlei deamons en server-programma's
opgestart worden (daar komen we zo nog op).
- Daarna wordt het programma voor de login-prompt gestart. Afhankelijk van
de hardware kan dat een normale login zijn in console of grafische mode,
maar het zou ook een login via een netwerk kunnen zijn.
Runlevel deel 2
Via inittab weet de computer nu, naar welk runlevel gegaan moet
worden. Maar hoe weet hij, wat daar allemaal voor moet gebeuren? Dat wordt
duidelijk gemaakt, door ieder runlevel een eigen directory te geven. Zo heet
de directory voor runlevel 5 /etc/rc.d/rc5.d (of voor andere
distributies /etc/rc5.d of /etc/init.d/rc5.d). In deze
directories staan de zgn. init-scripts. Elk script heeft de controle over een
eigen service, zoals een mail-server, een printer-stuurprogramma e.d.
Elk init-script heeft een bepaalde syntax: bij de aanroep ervan wordt
één argument meegegeven: start of stop,
afhankelijk van of de dienst gestart of gestopt moet worden. Veel scripts
kennen meer argumenten dan start en stop, maar die zijn
voor init niet belangrijk.
Bij het veranderen van runlevel voert init alle scripts in de
betreffende directory uit. Ga je bijvoorbeeld naar runlevel 2, dan worden
alle scripts in /etc/rc.d/rc2.d uitgevoerd:
$ ls /etc/rc.d/rc2.d
K09sshd S10network S30syslogd S75keytable
K75netfs S16apmd S40crond S90xfs
K89portmap S20random S60lpd S99local
S08ipchains |
Dit is natuurlijk maar een voorbeeld. Op je eigen systeem zou deze directory
er ook heel anders kunnen uitzien.
De naam van elk script bestaat uit 3 delen:
- Een hoofdletter K of S, die betekenen Kill
(stoppen) dan wel Start (...).
- Een twee-cijferig getal tussen 00 en 99, dat de volgorde aangeeft waarin
de scripts uitgevoerd worden.
- Een script-naam, om voor menselijke ogen duidelijk te maken wat het
script hoort te doen.
In ons voorbeeld worden de diensten sshd, netfs en
portmap gestopt, waarna daarna enkele andere diensten gestart
worden.
Belangrijk is erop te letten, dat diensten niet meerdere keren opgestart
worden. Bv. in runlevel 3 wordt de dienst network opgestart. Als
daarna wordt doorgeschakeld naar runlevel 5 (met bv.de opdracht telinit
5), en network wordt daar nogmaals opgestart, dan zouden de
netwerk-diensten 2x draaien. Het goed inrichten van dit systeem vereist dus
enige aandacht!
Het is trouwens bij de meeste distributies gebruikelijk, dat de init-scripts
in de verschillende runlevel-directories in feite (soft)-links zijn naar
scripts, die zich bevinden in /etc/init.d of
/etc/rc.d/init.d. Als je dus een bepaalde dienst op wilt starten,
staat het originele script in één van die directories en moet
je een link aanmaken in de betreffende runlevel-directory:
cd /etc/rc.d/rc5.d
ln -s ../init.d/mysql S97mysql
cd ../rc0.d
ln -s ../init.d/mysql K02mysql
cd ../rc1.d
ln -s ../init.d/mysql K02mysql
cd ../rc6.d
ln -s ../init.d/mysql k02mysql |
Het voordeel van dit systeem is, dat een verandering in een script slechts op
één plaats hoeft te worden verwerkt. Nog even een tip: als
je ergens een start-link maakt, zorg dan gelijk voor stop-links voor minimaal
de runlevels 0, 1 en 6.
Veel distributies hebben een eigen scriptje ontwikkeld om je al die moeite te
besparen. Bij RedHat heet dat script chkconfig, bij Debian
update-rc.d.
Slot
Nadat init klaar is komt je inlog-prompt of -scherm te voorschijn.
De computer staat nu geheel tot je beschikking!
Als je binnenkort eens een uurtje vrij hebt, moet je toch eens wat van die
init-scripts gaan bekijken: je leert er een hoop van. Pas echter wel op, dat
je er niets aan verandert: als je het init-proces in de war schopt, zou het
wel eens kunnen gebeuren, dat je computer niet meer op wil starten...!
Laatst herzien op 18-12-2006
|