Een inleiding tot de Linux opstart- en opstartprocessen

Inzicht in de Linux opstart- en opstartprocessen is belangrijk voor zowel het configureren van Linux als het oplossen van opstartproblemen. Dit artikel geeft een overzicht van de opstartvolgorde met behulp van de GRUB2-bootloader en de opstartvolgorde zoals die wordt uitgevoerd door het systemd-initialisatiesysteem.

In werkelijkheid zijn er twee opeenvolgingen van gebeurtenissen die nodig zijn om een Linux-computer op te starten en bruikbaar te maken: opstarten en opstarten. De boot-sequentie begint als de computer wordt aangezet, en is voltooid als de kernel is geïnitialiseerd en systemd wordt gestart. Het opstartproces neemt het dan over en voltooit de taak om de Linux computer in een operationele staat te brengen.

Over het geheel genomen is het Linux opstart- en opstartproces vrij eenvoudig te begrijpen. Het bestaat uit de volgende stappen, die in de volgende paragrafen gedetailleerder worden beschreven.

  • BIOS POST
  • Bootloader (GRUB2)
  • Kernelinitialisatie
  • Start systemd, de ouder van alle processen.

Merk op dat dit artikel GRUB2 en systemd behandelt omdat zij de huidige bootloader en initialisatiesoftware zijn voor de meeste grote distributies. Andere software opties zijn historisch gebruikt en zijn nog steeds te vinden in sommige distributies.

Het boot proces

Het boot proces kan op een van de volgende manieren gestart worden. Ten eerste, als de stroom is uitgeschakeld, zal het inschakelen van de stroom het opstartproces starten. Als de computer al een lokale gebruiker heeft, inclusief root of een gebruiker zonder rechten, kan de gebruiker het opstartproces programmatisch starten door de GUI of opdrachtregel te gebruiken om een reboot te starten. Bij een reboot wordt de computer eerst afgesloten en vervolgens opnieuw opgestart.

BIOS POST

De eerste stap van het Linux opstartproces heeft eigenlijk niets met Linux te maken. Dit is het hardwaregedeelte van het opstartproces en is voor elk besturingssysteem hetzelfde. Wanneer de computer voor het eerst wordt opgestart, wordt de POST (Power On Self Test) uitgevoerd, een onderdeel van het BIOS (Basic I/O System).

Toen IBM in 1981 de eerste PC ontwierp, werd het BIOS ontworpen om de hardware componenten te initialiseren. POST is het onderdeel van het BIOS dat ervoor moet zorgen dat de computerhardware correct functioneert. Als POST faalt, kan het zijn dat de computer niet bruikbaar is en het boot proces dus niet doorgaat.

BIOS POST controleert de basis operabiliteit van de hardware en geeft dan een BIOS interrupt, INT 13H, die de boot sectoren lokaliseert op alle aangesloten bootable devices. De eerste boot sector die een geldig boot record bevat wordt in RAM geladen en de controle wordt dan overgebracht naar de code die is geladen vanuit de boot sector.

De boot sector is eigenlijk de eerste fase van de boot loader. Er zijn drie boot loaders die door de meeste Linux distributies worden gebruikt, GRUB, GRUB2, en LILO. GRUB2 is de nieuwste en wordt tegenwoordig veel vaker gebruikt dan de andere oudere opties.

GRUB2

GRUB2 staat voor “GRand Unified Bootloader, version 2” en het is nu de primaire bootloader voor de meeste huidige Linux distributies. GRUB2 is het programma dat de computer net slim genoeg maakt om de kernel van het besturingssysteem te vinden en in het geheugen te laden. Omdat het gemakkelijker is om GRUB te schrijven en te zeggen dan GRUB2, mag ik in dit document de term GRUB gebruiken, maar ik zal verwijzen naar GRUB2 tenzij anders gespecificeerd.

GRUB is ontworpen om compatibel te zijn met de multiboot specificatie waardoor GRUB vele versies van Linux en andere vrije besturingssystemen kan booten; het kan ook het bootrecord van propriëtaire besturingssystemen keten laden.

GRUB kan de gebruiker ook laten kiezen om uit verschillende kernels voor een gegeven Linux distributie te booten. Dit biedt de mogelijkheid om op te starten naar een eerdere kernelversie als een bijgewerkte versie op de een of andere manier niet werkt of incompatibel is met een belangrijk stuk software. GRUB kan worden geconfigureerd met het bestand /boot/grub/grub.conf.

GRUB1 wordt nu als verouderd beschouwd en is in de meeste moderne distributies vervangen door GRUB2, dat een herschrijving is van GRUB1. Op Red Hat gebaseerde distro’s hebben een upgrade naar GRUB2 uitgevoerd rond Fedora 15 en CentOS/RHEL 7. GRUB2 biedt dezelfde boot functionaliteit als GRUB1 maar GRUB2 is ook een mainframe-achtige commando gebaseerde pre-OS omgeving en laat meer flexibiliteit toe tijdens de pre-boot fase. GRUB2 wordt geconfigureerd met /boot/grub2/grub.cfg.

De primaire functie van beide GRUB is om de Linux kernel in het geheugen te laden en aan de gang te krijgen. Beide versies van GRUB werken in essentie op dezelfde manier en hebben dezelfde drie stappen, maar ik zal GRUB2 gebruiken voor deze discussie over hoe GRUB zijn werk doet. De configuratie van GRUB of GRUB2 en het gebruik van GRUB2 commando’s valt buiten het bestek van dit artikel.

Hoewel GRUB2 officieel niet de stage notatie gebruikt voor de drie stages van GRUB2, is het handig om er op die manier naar te verwijzen, dus doe ik dat in dit artikel.

Stap 1

Zoals vermeld in de BIOS POST sectie, zoekt BIOS aan het eind van POST op de aangesloten schijven naar een boot record, meestal te vinden in de Master Boot Record (MBR), het laadt de eerste die het vindt in het geheugen en start dan de uitvoering van het boot record. De bootstrapcode, d.w.z. GRUB2 stage 1, is zeer klein omdat hij samen met de partitietabel in de eerste sector van 512 bytes op de harde schijf moet passen. De totale hoeveelheid ruimte die is toegewezen voor de eigenlijke bootstrap code in een klassieke generieke MBR is 446 bytes. Het 446 bytes bestand voor stage 1 heet boot.img en bevat niet de partitietabel die apart aan de boot record wordt toegevoegd.

Omdat de boot record zo klein moet zijn, is hij ook niet erg slim en begrijpt hij bestandssysteem structuren niet. Daarom is het enige doel van stage 1 het lokaliseren en laden van stage 1.5. Om dit te bereiken moet stage 1.5 van GRUB zich bevinden in de ruimte tussen de boot record zelf en de eerste partitie op de schijf. Nadat GRUB stage 1.5 in het RAM is geladen, geeft stage 1 de controle over aan stage 1.5.

Stage 1.5

Zoals hierboven vermeld, moet stage 1.5 van GRUB zich bevinden in de ruimte tussen de boot record zelf en de eerste partitie op de diskdrive. Deze ruimte werd historisch ongebruikt gelaten om technische redenen. De eerste partitie op de harde schijf begint op sector 63 en met de MBR in sector 0, blijven er 62 sectoren van 512 bytes-31.744 bytes over om het core.img bestand in op te slaan, dat stage 1.5 van GRUB is. Het core.img bestand is 25.389 bytes groot, dus er is genoeg ruimte beschikbaar tussen de MBR en de eerste schijf partitie om het in op te slaan.

Door de grotere hoeveelheid code die kan worden ondergebracht voor stage 1.5, kan het genoeg code bevatten om een paar veel voorkomende bestandssysteem drivers te bevatten, zoals de standaard EXT en andere Linux bestandssystemen, FAT, en NTFS. De GRUB2 core.img is veel complexer en capabeler dan de oudere GRUB1 stage 1.5. Dit betekent dat fase 2 van GRUB2 op een standaard EXT bestandssysteem kan worden geplaatst, maar niet op een logisch volume. Dus de standaard locatie voor de fase 2 bestanden is in het /boot bestandssysteem, specifiek /boot/grub2.

Merk op dat de /boot directory zich op een bestandssysteem moet bevinden dat wordt ondersteund door GRUB. Niet alle bestandssystemen worden ondersteund. De functie van stage 1.5 is om de uitvoering te starten met de bestandssysteem drivers die nodig zijn om de stage 2 bestanden te lokaliseren in het /boot bestandssysteem en de benodigde drivers te laden.

Stage 2

Alle bestanden voor GRUB stage 2 bevinden zich in de /boot/grub2 directory en verschillende subdirectories. GRUB2 heeft geen image bestand zoals stadium 1 en 2. In plaats daarvan bestaat het voornamelijk uit runtime kernel modules die naar behoefte worden geladen vanuit de /boot/grub2/i386-pc directory.

De functie van GRUB2 stage 2 is het lokaliseren en laden van een Linux kernel in RAM en de controle van de computer over te dragen aan de kernel. De kernel en de bijbehorende bestanden bevinden zich in de /boot directory. De kernelbestanden zijn identificeerbaar omdat ze allemaal beginnen met de naam vmlinuz. U kunt de inhoud van de /boot directory opvragen om de huidige geïnstalleerde kernels op uw systeem te zien.

GRUB2, net als GRUB1, ondersteunt het booten vanuit een selectie van Linux kernels. De Red Hat pakketbeheerder, DNF, ondersteunt het bewaren van meerdere versies van de kernel, zodat als er een probleem optreedt met de nieuwste, een oudere versie van de kernel kan worden opgestart. Standaard biedt GRUB een pre-boot menu van de geïnstalleerde kernels, inclusief een reddingsoptie en, indien geconfigureerd, een hersteloptie.

Stap 2 van GRUB2 laadt de geselecteerde kernel in het geheugen en geeft de controle over de computer over aan de kernel.

Kernel

Alle kernels zijn in een zelf-uitpakkend, gecomprimeerd formaat om ruimte te besparen. De kernels bevinden zich in de /boot directory, samen met een initiële RAM disk image, en device maps van de harde schijven.

Nadat de geselecteerde kernel in het geheugen is geladen en begint met uitvoeren, moet het eerst zichzelf uitpakken uit de gecomprimeerde versie van het bestand voordat het enig nuttig werk kan verrichten. Zodra de kernel zichzelf heeft uitgepakt, laadt het systemd, wat de vervanger is van het oude SysV init programma, en draagt de controle over aan het.

Dit is het einde van het boot proces. Op dit punt draaien de Linux kernel en systemd, maar kunnen geen productieve taken uitvoeren voor de eindgebruiker omdat er niets anders draait.

Het opstartproces

Het opstartproces volgt op het opstartproces en brengt de Linux computer in een operationele staat waarin het bruikbaar is voor productief werk.

systemd

systemd is de moeder van alle processen en het is verantwoordelijk voor het in een staat brengen van de Linux host waarin productief werk kan worden gedaan. Sommige van zijn functies, die veel uitgebreider zijn dan het oude init programma, zijn het beheren van vele aspecten van een draaiende Linux host, inclusief het mounten van bestandssystemen, en het starten en beheren van systeemdiensten die nodig zijn om een productieve Linux host te hebben. Alle taken van systemd die niet gerelateerd zijn aan de opstartvolgorde vallen buiten het bereik van dit artikel.

Eerst mount systemd de bestandssystemen zoals gedefinieerd door /etc/fstab, inclusief eventuele swap bestanden of partities. Op dit punt heeft het toegang tot de configuratiebestanden in /etc, inclusief zijn eigen. Het gebruikt zijn configuratiebestand, /etc/systemd/system/default.target, om te bepalen in welke toestand of doel, het de host moet booten. Het default.target bestand is slechts een symbolische link naar het echte target bestand. Voor een desktop werkstation zal dit typisch het grafische.target zijn, wat gelijk staat aan runlevel 5 in het oude SystemV init. Voor een server is de standaard waarschijnlijk de multi-user.target, die lijkt op runlevel 3 in SystemV. De emergency.target is vergelijkbaar met single user mode.

Noteer dat targets en services systemd units zijn.

Tabel 1, hieronder, is een vergelijking van de systemd targets met de oude SystemV opstart runlevels. De systemd target aliassen worden geleverd door systemd voor achterwaartse compatibiliteit. De target aliassen maken het mogelijk dat scripts – en veel sysadmins zoals ikzelf – SystemV commando’s zoals init 3 kunnen gebruiken om runlevels te veranderen. Of course, the SystemV commands are forwarded to systemd for interpretation and execution.

SystemV Runlevel systemd target systemd target aliases Description
halt.target Halts the system without powering it down.
0 poweroff.target runlevel0.target Halts the system and turns the power off.
S emergency.target Single user mode. No services are running; filesystems are not mounted. This is the most basic level of operation with only an emergency shell running on the main console for the user to interact with the system.
1 rescue.target runlevel1.target A base system including mounting the filesystems with only the most basic services running and a rescue shell on the main console.
2 runlevel2.target Multiuser, without NFS but all other non-GUI services running.
3 multi-user.target runlevel3.target All services running but command line interface (CLI) only.
4 runlevel4.target Unused.
5 graphical.target runlevel5.target multi-user with a GUI.
6 reboot.target runlevel6.target Reboot
default.target This target is always aliased with a symbolic link to either multi-user.target or graphical.target. systemd always uses the default.target to start the system. Het standaard.doel mag nooit worden gekoppeld aan halt.doel, poweroff.doel, of reboot.doel.

Tabel 1: Vergelijking van SystemV runlevels met systemd doelen en enkele doel aliassen.

Elk doel heeft een set afhankelijkheden die worden beschreven in het configuratiebestand. systemd start de vereiste afhankelijkheden op. Deze afhankelijkheden zijn de diensten die nodig zijn om de Linux host op een specifiek niveau van functionaliteit te draaien. Wanneer alle afhankelijkheden die in de doel configuratie bestanden staan, geladen zijn en draaien, draait het systeem op dat doel niveau.

systemd kijkt ook naar de legacy SystemV init directories om te zien of er daar opstart bestanden staan. Als dat zo is, gebruikt systemd die als configuratiebestanden om de services te starten die door de bestanden worden beschreven. De afgeschreven netwerk dienst is een goed voorbeeld van een van die diensten die nog steeds SystemV opstart bestanden gebruiken in Fedora.

Figuur 1, hieronder, is rechtstreeks gekopieerd van de bootup man page. Het toont de algemene volgorde van gebeurtenissen tijdens het opstarten van systemd en de basis volgorde vereisten om een succesvolle opstart te verzekeren.

De sysinit.target en basic.target targets kunnen worden beschouwd als controleposten in het opstart proces. Hoewel systemd als een van zijn ontwerpdoelen heeft om systeemdiensten parallel te starten, zijn er nog steeds bepaalde diensten en functionele doelen die moeten worden gestart voordat andere diensten en doelen kunnen worden gestart. Deze controlepunten kunnen niet worden gepasseerd totdat aan alle diensten en doelen die door dat controlepunt worden vereist, is voldaan.

Dus het sysinit.doel wordt bereikt wanneer alle eenheden waarvan het afhankelijk is, zijn voltooid. Al deze units, het mounten van bestandssystemen, het instellen van swap bestanden, het starten van udev, het instellen van de random generator seed, het starten van low-level services, en het instellen van cryptografische services als een of meer bestandssystemen zijn versleuteld, moeten worden voltooid, maar binnen het sysinit.target kunnen deze taken parallel worden uitgevoerd.

Het sysinit.target start alle low-level services en units op die nodig zijn om het systeem marginaal te laten functioneren en die nodig zijn om door te kunnen gaan naar het basic.target.

local-fs-pre.target
|
v
(various mounts and (various swap (various cryptsetup
fsck services...) devices...) devices...) (various low-level (various low-level
| | | services: udevd, API VFS mounts:
v v v tmpfiles, random mqueue, configfs,
local-fs.target swap.target cryptsetup.target seed, sysctl, ...) debugfs, ...)
| | | | |
\__________________|_________________ | ___________________|____________________/
\|/
v
sysinit.target
|
____________________________________/|\________________________________________
/ | | | \
| | | | |
v v | v v
(various (various | (various rescue.service
timers...) paths...) | sockets...) |
| | | | v
v v | v rescue.target
timers.target paths.target | sockets.target
| | | |
v \_________________ | ___________________/
\|/
v
basic.target
|
____________________________________/| emergency.service
/ | | |
| | | v
v v v emergency.target
display- (various system (various system
manager.service services services)
| required for |
| graphical UIs) v
| | multi-user.target
| | |
\_________________ | _________________/
\|/
v
graphical.target

Figuur 1: De systemd startup map.

Nadat aan het sysinit.target is voldaan, start systemd vervolgens het basic.target, waarbij alle units worden gestart die nodig zijn om het te vervullen. Het basisdoel biedt wat extra functionaliteit door eenheden te starten die nodig zijn voor het volgende doel. Dit zijn onder andere het instellen van paden naar uitvoerbare mappen, communicatie sockets en timers.

Ten slotte kunnen de doelen op gebruikersniveau, multi-user.doel of grafisch.doel, worden geïnitialiseerd. Merk op dat het multi-user.target moet worden bereikt voordat aan de afhankelijkheden van het grafische target kan worden voldaan.

De onderstreepte targets in Figuur 1, zijn de gebruikelijke opstart targets. Als een van deze doelen is bereikt, is het opstarten voltooid. Als het multi-user.target de standaard is, dan zou je een tekstmodus login op de console moeten zien. Als graphical.target de standaard is, dan zou u een grafische login moeten zien; het specifieke GUI login scherm dat u ziet hangt af van de standaard display manager die u gebruikt.

Issues

Ik had onlangs de behoefte om de standaard boot kernel te veranderen op een Linux computer die GRUB2 gebruikte. Ik ontdekte dat sommige commando’s niet goed leken te werken, of dat ik ze niet correct gebruikte. Ik weet nog niet zeker wat het geval was, en moet nog wat meer onderzoek doen.

Het grub2-set-default commando stelde de standaard kernel index voor mij niet goed in in het /etc/default/grub bestand, zodat de gewenste alternatieve kernel niet opstartte. Dus veranderde ik handmatig /etc/default/grub GRUB_DEFAULT=saved in GRUB_DEFAULT=2 waarbij 2 de index is van de geïnstalleerde kernel die ik wilde booten. Daarna heb ik het commando grub2-mkconfig > /boot/grub2/grub.cfg uitgevoerd om het nieuwe grub configuratie bestand aan te maken. Deze omzeiling werkte zoals verwacht en bootte naar de alternatieve kernel.

Conclusies

GRUB2 en het systemd init systeem zijn de belangrijkste componenten in de boot en opstart fases van de meeste moderne Linux distributies. Ondanks het feit dat er controverse is geweest rond systemd in het bijzonder, werken deze twee componenten soepel samen om eerst de kernel te laden en vervolgens alle systeemdiensten op te starten die nodig zijn om een functioneel Linux systeem te produceren.

Hoewel ik zowel GRUB2 als systemd complexer vind dan hun voorgangers, zijn ze ook net zo makkelijk te leren en te beheren. De man pagina’s bevatten veel informatie over systemd, en freedesktop.org heeft de complete set van systemd man pagina’s online staan. Zie de bronnen, hieronder, voor meer links.