Systémové volání kexec
umožňuje Linuxu nahradit aktuálně běžící jádro novým. Hned ze začátku je však třeba uklidnit přehnaná očekávání, která tato slovníková definice může způsobit. Jedná se totiž o analogii běžného unixového volání exec
, které tvoří spolu s voláním fork
běžný způsob vzniku nového procesu. Každý proces, kromě procesu s číslem 1, který je vytvořen jádrem po startu, vzniká tak, že se existující proces voláním fork
rozdvojí na pár rodiče a dítě, a zatímco rodič pokračuje dál, dítě vzápětí zavolá funkci exec
, čímž nahradí kód původního procesu kódem nového.
V případě výměny jádra odpadá část s rozdvojením procesu, protože jádro není proces a běží vždy právě jedno. Jde tak pouze o nahrazení jádra novým, přičemž při spuštění nového jádra staré přestane existovat a ztratí se i veškerý jeho vnitřní stav. Protože vnitřním stavem jádra jsou i všechny běžící procesy a připojené souborové systémy, znamená výměna jádra prakticky restart systému. Také se dá říct, že volání kexec
dělá z Linuxu zavaděč pro jiný Linux.
Praktické použití
Analogie se zavaděčem odpovídá i tomu, jak se dá kexec
prakticky použít. Je k tomu potřeba stejnojmenná utilita z balíčku kexec-tools
. Ta pracuje podobně jako třeba zavaděč GRUB ve dvou krocích − nejprve je do paměti nahrán obraz jádra, jeho parametry a případně i startovací RAMdisk a pak je v druhém kroku jádro spuštěno.
První krok provedeme třeba takto:
# kexec --load /boot/vmlinuz --initrd /boot/initramfs --append root=/dev/sda1
Pomocí přepínače --reuse-cmdline
můžeme novému jádru předat stejné parametry příkazového řádku, jako používá aktuálně běžící jádro, obdobně lze předat i aktuálně používaný startovací RAMdisk. Tady je však potřeba upozornit, že startovací RAMdisky (přesněji řečeno initramfs
) obvykle obsahují moduly pro příslušné jádro, takže pokud má být nahráno jiné než aktuálně běžící jádro, pravděpodobně nebude se zachováním starého RAMdisku fungovat. Pro distribuce založené na Debianu lze s výhodou využít symbolických odkazů na aktuální jádro a RAMdisk přímo v kořeni souborového systému, takto:
# kexec --load /vmlinuz --initrd=/initrd.img --reuse-cmdline
Druhý krok nemusíme řešit
Jádro máme zavedeno, zbývá ho tedy jen spustit příkazem kexec --exec
. Tohle ale doma nezkoušejte. Příkaz totiž zafunguje okamžitě a začne startovat nové jádro, zatímco to staré − se spuštěnými procesy, připojenými souborovými systémy a nezapsanými diskovými buffery − přestane existovat. Prakticky tedy dojde k ekvivalentu stisku tlačítka reset.
Je tedy potřeba tento příkaz volat až po řádném ukončení všech procesů a odpojení všech disků, zkrátka jako při klasickém měkkém restartu počítače. Tady přichází dobrá zpráva: toto už je v distribucích zařízeno. Všechny distribuce, které jsem testoval, mají ve své vypínací sekvenci na samotném konci test, zda má kexec
připravené nové jádro ke spuštění. Pokud ne, je proveden klasický restart, pokud ano, je spuštěno nové jádro a restart je tak zkrácen na zcela minimální dobu.
Poznámku si ještě zaslouží příkaz systemctl kexec
. Ten by měl zcela automaticky provést restart pomocí kexec
, jeho funkce ovšem závisí na použití zavaděče systemd-boot
. Žádný systém s tímto zavaděčem nemám po ruce, takže jsem tuto funkci nemohl vyzkoušet.
K čemu lze rychlý restart použít
Může se zdát, že výhoda v používání volání kexec
není velká. Zejména moderní laptopy zkrátily POST na naprosté minimum, takže rozdíl mezi restartem a použitím volání kexec
bude jen ve zdržení odpočtem v menu GRUBu. Podobná situace bude platit pro virtuální servery, jako na této ukázce. Přesto se najdou případy, kdy se použití kexec
může vyplatit.
Tím prvním je použití s plně šifrovaným diskem, kdy je šifrován i oddíl /boot
a heslo je tedy potřeba zadat už do GRUBu, aby se vůbec dostal k šifrovanému obrazu jádra a startovacímu RAMdisku. Protože GRUB nedokáže předat rozšifrovaný oddíl startujícímu jádru, používá se v tomto nastavení trik, kdy je klíč schován do (šifrovaného) startovacího RAMdisku. Díky tomu není potřeba zadávat heslo dvakrát. Při použití kexec
pak není nutné heslo zadávat vůbec, protože je předáno přímo pomocí startovacího RAMdisku.
Druhou velkou výhodu představuje použití volání kexec
na profesionálním serverovém hardwaru. Snad každý, kdo se někdy osobně prováděl restart ve studené uličce datacentra, dokáže potvrdit, že POST u těchto serverů trvá nekonečně dlouho − pět minut je naprosté minimum. Pokud během výpadku serveru dojde k výpadku poskytované služby, je dost velký rozdíl, jestli ten výpadek bude trvat desítky sekund nebo jednotky minut.
Aktualizace mikrokódu se bez plného restartu neobejde
Existuje jedna výjimka, kdy restart pomocí volání kexec
není plnohodnotnou náhradou běžného restartu. Je to v případě, kdy obraz initramfs obsahuje kromě startovacího souborového systému také aktualizaci mikrokódu. Tu kexec
provést neumí.
Závěrem se hodí také napsat, že samozřejmě všechny ty procesy, které se v počítači dějí během POSTu, nejsou úplně samoúčelné; občasný reset může pomoci vrátit celý počítač do jasně definovaného výchozího stavu, což kexec
nedokáže. Jako každý nástroj je tedy potřeba používat jej s citem ke konkrétnímu účelu, tedy například rychlé výměně jádra s minimálním výpadkem služeb.