Úvod do zaváděcích a spouštěcích procesů systému Linux

Znalost zaváděcích a spouštěcích procesů systému Linux je důležitá jak pro konfiguraci systému Linux, tak pro řešení problémů se spouštěním. Tento článek představuje přehled zaváděcí sekvence pomocí zavaděče GRUB2 a spouštěcí sekvence, jak ji provádí inicializační systém systemd.

Ve skutečnosti existují dvě sekvence událostí, které jsou nutné ke spuštění počítače se systémem Linux a jeho použitelnosti: zavádění a spouštění. Zaváděcí sekvence začíná při zapnutí počítače a je dokončena po inicializaci jádra a spuštění systemd. Proces spouštění pak přebírá a dokončuje úkol uvedení počítače se systémem Linux do provozuschopného stavu.

Celkově je proces zavádění a spouštění systému Linux poměrně jednoduchý na pochopení. Skládá se z následujících kroků, které budou podrobněji popsány v následujících částech.

  • BIOS POST
  • Zavaděč systému (GRUB2)
  • Inicializace jádra
  • Spuštění systemd, nadřazeného systému všech procesů.

Všimněte si, že tento článek se zabývá GRUB2 a systemd, protože se jedná o aktuální zavaděč a inicializační software většiny hlavních distribucí. Historicky se používaly i jiné možnosti softwaru a v některých distribucích se stále vyskytují.

Zaváděcí proces

Zaváděcí proces lze zahájit jedním z několika způsobů. Za prvé, pokud je vypnuto napájení, zapnutím napájení se zahájí zaváděcí proces. Pokud na počítači již pracuje místní uživatel, včetně uživatele root nebo neprivilegovaného uživatele, může uživatel programově zahájit spouštěcí sekvenci pomocí grafického uživatelského rozhraní nebo příkazového řádku a zahájit restart. Restart provede nejprve vypnutí a poté restart počítače.

BIOS POST

První krok zaváděcího procesu systému Linux ve skutečnosti nemá s Linuxem nic společného. Jedná se o hardwarovou část zaváděcího procesu a je stejná pro jakýkoli operační systém. Při prvním zapnutí počítače se spustí POST (Power On Self Test), který je součástí systému BIOS (Basic I/O System).

Když společnost IBM v roce 1981 navrhla první počítač, byl systém BIOS navržen tak, aby inicializoval hardwarové komponenty. POST je část systému BIOS, jejímž úkolem je zajistit správnou funkci hardwaru počítače. Pokud POST selže, počítač nemusí být použitelný, a proto proces zavádění systému nepokračuje.

POST systému BIOS zkontroluje základní funkčnost hardwaru a poté vydá přerušení systému BIOS, INT 13H, které vyhledá zaváděcí sektory na všech připojených zaváděcích zařízeních. První nalezený zaváděcí sektor, který obsahuje platný zaváděcí záznam, je načten do paměti RAM a řízení je poté přeneseno na kód, který byl načten ze zaváděcího sektoru.

Zaváděcí sektor je ve skutečnosti prvním stupněm zavaděče. Ve většině linuxových distribucí se používají tři zavaděče: GRUB, GRUB2 a LILO. GRUB2 je nejnovější a v současné době se používá mnohem častěji než ostatní starší možnosti.

GRUB2

GRUB2 je zkratka pro „GRand Unified Bootloader, version 2“ a v současné době je hlavním zavaděčem většiny současných distribucí Linuxu. GRUB2 je program, díky kterému je počítač natolik inteligentní, že dokáže najít jádro operačního systému a načíst ho do paměti. Protože je jednodušší napsat a vyslovit GRUB než GRUB2, mohu v tomto dokumentu používat termín GRUB, ale pokud není uvedeno jinak, budu mluvit o GRUB2.

GRUB byl navržen tak, aby byl kompatibilní se specifikací multiboot, která umožňuje GRUBu zavádět mnoho verzí Linuxu a dalších svobodných operačních systémů; může také řetězově načítat zaváděcí záznamy proprietárních operačních systémů.

GRUB také může uživateli umožnit výběr zavádění z několika různých jader dané distribuce Linuxu. To poskytuje možnost zavést systém z předchozí verze jádra, pokud aktualizované jádro nějakým způsobem selže nebo je nekompatibilní s důležitým softwarem. GRUB lze nakonfigurovat pomocí souboru /boot/grub/grub.conf.

GRUB1 je nyní považován za zastaralý a ve většině moderních distribucí byl nahrazen GRUB2, který je přepisem GRUB1. Distribuce založené na systému Red Hat přešly na GRUB2 kolem Fedory 15 a CentOS/RHEL 7. GRUB2 poskytuje stejné zaváděcí funkce jako GRUB1, ale GRUB2 je také příkazové prostředí před spuštěním systému podobné mainframe a umožňuje větší flexibilitu ve fázi před spuštěním systému. GRUB2 se konfiguruje pomocí souboru /boot/grub2/grub.cfg.

Primární funkcí obou GRUBů je načtení linuxového jádra do paměti a jeho spuštění. Obě verze GRUBu pracují v podstatě stejně a mají stejné tři fáze, ale pro tuto diskusi o tom, jak GRUB vykonává svou práci, budu používat GRUB2. Konfigurace GRUBu nebo GRUB2 a používání příkazů GRUB2 je mimo rozsah tohoto článku.

Ačkoli GRUB2 oficiálně nepoužívá pro tři fáze GRUBu2 zápis etap, je vhodné se na ně takto odkazovat, proto to v tomto článku udělám.

Stupeň 1

Jak bylo zmíněno v části POST systému BIOS, na konci POST systém BIOS prohledá připojené disky a vyhledá zaváděcí záznam, který se obvykle nachází v hlavním zaváděcím záznamu (MBR), první nalezený načte do paměti a poté zahájí provádění zaváděcího záznamu. Zaváděcí kód, tj. fáze 1 GRUB2, je velmi malý, protože se musí vejít do prvního 512bajtového sektoru na pevném disku spolu s tabulkou oddílů. Celkový prostor vyhrazený pro vlastní zaváděcí kód v klasickém obecném MBR je 446 bajtů. Soubor o velikosti 446 bajtů pro fázi 1 se jmenuje boot.img a neobsahuje tabulku oddílů, která se do zaváděcího záznamu přidává samostatně.

Protože zaváděcí záznam musí být tak malý, není také příliš inteligentní a nerozumí strukturám souborového systému. Proto je jediným účelem fáze 1 vyhledat a načíst fázi 1.5. Aby toho bylo možné dosáhnout, musí být fáze 1.5 GRUBu umístěna v prostoru mezi samotným zaváděcím záznamem a prvním oddílem na disku. Po načtení fáze 1.5 systému GRUB do paměti RAM předá fáze 1 řízení fázi 1.5.

Fáze 1.5

Jak bylo uvedeno výše, fáze 1.5 systému GRUB musí být umístěna v prostoru mezi samotným zaváděcím záznamem a prvním oddílem na disku. Tento prostor byl historicky z technických důvodů ponechán nevyužitý. První oddíl na pevném disku začíná v sektoru 63 a s MBR v sektoru 0 zbývá 62 512bajtových sektorů – 31 744 bajtů – pro uložení souboru core.img, který je fází 1.5 systému GRUB. Soubor core.img má 25 389 bajtů, takže mezi MBR a prvním diskovým oddílem je k dispozici dostatek místa, kam jej lze uložit.

Vzhledem k většímu množství kódu, které lze do fáze 1.5 umístit, může mít dostatek kódu pro několik běžných ovladačů souborových systémů, jako je standardní EXT a další linuxové souborové systémy, FAT a NTFS. Soubor GRUB2 core.img je mnohem složitější a schopnější než starší GRUB1 fáze 1.5. To znamená, že fázi 2 GRUB2 lze umístit na standardní souborový systém EXT, ale nelze ji umístit na logický svazek. Standardní umístění souborů fáze 2 je tedy v souborovém systému /boot, konkrétně /boot/grub2.

Všimněte si, že adresář /boot musí být umístěn na souborovém systému, který je podporován systémem GRUB. Ne všechny souborové systémy to umožňují. Úkolem fáze 1.5 je zahájit provádění s ovladači souborového systému potřebnými k nalezení souborů fáze 2 v souborovém systému /boot a načtení potřebných ovladačů.

Fáze 2

Všechny soubory pro fázi 2 systému GRUB jsou umístěny v adresáři /boot/grub2 a několika podadresářích. GRUB2 nemá soubor s obrazem jako fáze 1 a 2. Místo toho se skládá převážně ze spouštěcích modulů jádra, které se podle potřeby načítají z adresáře /boot/grub2/i386-pc.

Úkolem fáze 2 systému GRUB2 je vyhledat a načíst jádro systému Linux do paměti RAM a předat jádru řízení počítače. Jádro a související soubory jsou umístěny v adresáři /boot. Soubory jádra jsou identifikovatelné, protože jsou všechny pojmenovány počínaje vmlinuz. Obsah adresáře /boot můžete vypsat a zjistit, jaká jádra jsou v systému aktuálně nainstalována.

GRUB2, stejně jako GRUB1, podporuje spouštění z jednoho z vybraných linuxových jader. Správce balíčků Red Hat, DNF, podporuje uchovávání více verzí jádra, takže pokud se vyskytne problém s nejnovější verzí, lze zavést starší verzi jádra. Ve výchozím nastavení poskytuje GRUB nabídku nainstalovaných jader před spuštěním, včetně možnosti záchrany a, pokud je nakonfigurována, možnosti obnovení.

Fáze 2 GRUB2 načte vybrané jádro do paměti a předá jádru řízení počítače.

Jádro

Všechna jádra jsou v samorozbalovacím, komprimovaném formátu pro úsporu místa. Jádra jsou umístěna v adresáři /boot spolu s počátečním obrazem disku RAM a mapami zařízení pevných disků.

Poté, co je vybrané jádro načteno do paměti a začne se vykonávat, musí se nejprve samo rozbalit z komprimované verze souboru, aby mohlo vykonávat užitečnou práci. Jakmile se jádro samo extrahuje, načte systemd, což je náhrada za starý iniciační program SysV, a předá mu řízení.

Tímto proces zavádění systému končí. V tomto okamžiku běží jádro Linuxu a systemd, ale nejsou schopny vykonávat žádné produktivní úkoly pro koncového uživatele, protože nic jiného neběží.

Proces spouštění

Proces spouštění následuje po procesu zavádění a uvádí počítač Linux do provozního stavu, ve kterém je použitelný pro produktivní práci.

systemd

systemd je matkou všech procesů a je zodpovědný za uvedení hostitele Linuxu do stavu, ve kterém lze vykonávat produktivní práci. Některé z jeho funkcí, které jsou mnohem rozsáhlejší než u starého programu init, spočívají ve správě mnoha aspektů běžícího hostitele Linuxu, včetně připojování souborových systémů a spouštění a správy systémových služeb potřebných k produktivní práci hostitele Linuxu. Všechny úlohy systemd, které nesouvisejí se spouštěcí sekvencí, jsou mimo rozsah tohoto článku.

Nejprve systemd připojí souborové systémy definované v souboru /etc/fstab, včetně všech odkládacích souborů nebo oddílů. V tomto okamžiku může přistupovat ke konfiguračním souborům umístěným v /etc, včetně svých vlastních. Pomocí svého konfiguračního souboru /etc/systemd/system/default.target určí, do jakého stavu nebo cíle má hostitele zavést. Soubor default.target je pouze symbolickým odkazem na skutečný cílový soubor. Pro desktopovou pracovní stanici to obvykle bude graphical.target, což odpovídá runlevelu 5 ve starém initu SystemV. U serveru bude výchozím souborem spíše víceuživatelský.target, který odpovídá runlevelu 3 v SystemV. Nouzový.cíl je podobný režimu jednoho uživatele.

Všimněte si, že cíle a služby jsou jednotky systemd.

Níže uvedená tabulka 1 představuje srovnání cílů systemd se starými úrovněmi spouštění SystemV. Aliasy targetů systemd jsou poskytovány systemd kvůli zpětné kompatibilitě. Cílové aliasy umožňují skriptům – a mnoha sysadminům, jako jsem já – používat příkazy SystemV, jako je init 3, ke změně úrovní spouštění. 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. Výchozí.target by nikdy neměl být aliasován na halt.target, poweroff.target nebo reboot.target.

Tabulka 1: Porovnání úrovní běhu SystemV s cíli systemd a některými aliasy cílů.

Každý cíl má sadu závislostí popsaných ve svém konfiguračním souboru. systemd spouští požadované závislosti. Tyto závislosti jsou služby potřebné pro běh linuxového hostitele na určité úrovni funkčnosti. Když jsou všechny závislosti uvedené v konfiguračních souborech cíle načteny a spuštěny, systém běží na dané úrovni cíle.

systemd se také podívá do starších init adresářů SystemV, aby zjistil, zda v nich existují nějaké spouštěcí soubory. Pokud ano, systemd je použije jako konfigurační soubory pro spuštění služeb popsaných v těchto souborech. Zastaralá síťová služba je dobrým příkladem jedné z těch, které ve Fedoře stále používají spouštěcí soubory SystemV.

Obrázek 1 níže je zkopírován přímo z manuálové stránky bootup. Ukazuje obecnou posloupnost událostí při spouštění systému systemd a základní pořadí požadavků pro zajištění úspěšného spuštění.

Cíle sysinit.target a basic.target lze považovat za kontrolní body v procesu spouštění. Přestože jedním z cílů návrhu systemd je paralelní spouštění systémových služeb, stále existují určité služby a funkční cíle, které musí být spuštěny dříve, než mohou být spuštěny jiné služby a cíle. Tyto kontrolní body nelze překročit, dokud nejsou splněny všechny služby a cíle požadované daným kontrolním bodem.

Takže cíl sysinit.target je dosažen, když jsou dokončeny všechny jednotky, na kterých závisí. Všechny tyto jednotky, připojování souborových systémů, nastavení odkládacích souborů, spuštění udev, nastavení osiva generátoru náhodných čísel, spuštění nízkoúrovňových služeb a nastavení kryptografických služeb, pokud je jeden nebo více souborových systémů šifrováno, musí být dokončeny, ale v rámci sysinit.target mohou být tyto úlohy prováděny paralelně.

Sysinit.target spustí všechny nízkoúrovňové služby a jednotky potřebné k tomu, aby byl systém alespoň okrajově funkční a aby bylo možné přejít k 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

Obrázek 1: Mapa spouštění systemd.

Po splnění sysinit.target systemd spustí basic.target a spustí všechny jednotky potřebné k jeho splnění. Základní cíl poskytuje některé další funkce tím, že spouští jednotky, které jsou vyžadovány pro další cíl. Mezi ně patří například nastavení cest k různým spustitelným adresářům, komunikačních soketů a časovačů.

Nakonec lze inicializovat cíle na uživatelské úrovni, víceuživatelský.target nebo grafický.target. Všimněte si, že před splněním závislostí grafického cíle musí být dosaženo cíle multi-user.target.

Podtržené cíle na obrázku 1, jsou obvyklé spouštěcí cíle. Když je některého z těchto cílů dosaženo, pak bylo spuštění dokončeno. Pokud je výchozí cíl multi-user.target, pak by se na konzole mělo zobrazit přihlášení v textovém režimu. Pokud je výchozí grafický.cíl, pak byste měli vidět přihlášení v grafickém režimu; konkrétní přihlašovací obrazovka grafického rozhraní bude záviset na výchozím správci zobrazení, který používáte.

Problémy

Nedávno jsem potřeboval změnit výchozí spouštěcí jádro v počítači se systémem Linux, který používal GRUB2. Zjistil jsem, že mi některé příkazy nefungují správně nebo že je nepoužívám správně. Zatím si nejsem jistý, co z toho bylo, a musím provést další výzkum.

Příkaz grub2-set-default mi správně nenastavil index výchozího jádra v souboru /etc/default/grub, takže požadované alternativní jádro se nezavedlo. Proto jsem ručně změnil /etc/default/grub GRUB_DEFAULT=saved na GRUB_DEFAULT=2, kde 2 je index nainstalovaného jádra, které jsem chtěl zavést. Pak jsem spustil příkaz grub2-mkconfig > /boot/grub2/grub.cfg pro vytvoření nového konfiguračního souboru grubu. Toto obejití fungovalo podle očekávání a došlo k zavedení alternativního jádra.

Závěry

GRUB2 a iniciační systém systemd jsou klíčové součásti zaváděcí a startovací fáze většiny moderních linuxových distribucí. Navzdory tomu, že zejména kolem systemd se objevily kontroverze, tyto dvě součásti hladce spolupracují, aby nejprve načetly jádro a poté spustily všechny systémové služby potřebné k vytvoření funkčního linuxového systému.

Přestože GRUB2 i systemd považuji za složitější než jejich předchůdce, jsou také stejně snadno naučitelné a spravovatelné. Stránky man obsahují velké množství informací o systemd a na webu freedesktop.org je k dispozici kompletní sada manuálových stránek systemd online. Další odkazy naleznete v níže uvedených zdrojích.