Práce v prostředí ramdisku

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání

Zavaděč

Zavaděč je standalone binární aplikace, která se stará o zavedení binárního jádra operačního systému do paměti počítače a jeho spuštění. Tato aplikace musí být schopna rozpoznat blokové zařízení a přečíst souborový systém na kterém má operační systém své jádro uložen.


O spuštění zavaděče se stará BIOS (resp. UEFI) počítače.

Nejrozšířenějším linuxovým zavaděčem je v současné době GRUB2, který má oproti staršímu zavaděči LILO výhodu především v tom, že jeho zaváděcí proces je velmi podobný tomu, jak funguje zavádění linuxového systému.

BIOS
BIOS sáhne vždy na první sektor blokového zařízení (tzv. MBR - Master Boot Record), kde se pokusí najít informaci o tom, odkud a kolik bajtů dat má natáhnout do paměti. Poté předá další řízení načtenému kódu.
UEFI
Supluje roli zavaděče a umožňuje zavést přímo jádro operačního systému. Předpokládá, že jádro je uloženo na diskovém oddíle se souborovým systémem FAT, ve formě binárního souboru. Místo binárního jádra OS mu lze předhodit zavaděč.
Upozornění Součástí načteného a spuštěného binárního kódu musí být vždy ovladače, které umožní další pokračování zaváděcího procesu. Bez ohledu na to, jde-li o zavaděč, nebo jádro operačního systému. Pokud některý z nich chybí, zavádění selže.
Kód natahovaný do paměti BIOSem, musí být vždy uložen na začátku disku, v prostoru mezi tabulkou rozdělení disku a začátkem prvního diskového oddílu. To v případě MS-DOS tabulky představovalo původně 62 datových bloků (cca 32 kB). Do tohoto prostoru se musel vejít veškerý kód zavaděče.

Více místa bylo mezi začátkem diskového oddílu a začátkem souborového systému (cca 66 kB). Toho využívala první verze zavaděče GRUB, která si na začátek disku uložila pouze malou část kódu, která si pak místo BIOSu natáhla do paměti vlastní kód zavaděče, uložený na začátku některého z diskových oddílů.

Tento koncept však přestal být s rostoucím množstvím existujícího hardware neudržitelný, protože nebylo možné do tak malého prostoru vtěsnat všechny potřebné ovladače. GRUB2, který nahradil původní verzi, používá podobný modulární koncept, jako linuxový kernel.

Na začátku disku je uloženo jádro s ovladači pro zpřístupnění adresáře s moduly a pak už lze natahovat moduly podle potřeby buďto manuálně z prostředí integrovaného shellu, nebo prostřednictvím konfiguračního souboru grub.cfg (GRUB legacy používal menu.lst).

Integrovaný shell, který umožňuje v průběhu zaváděcího procesu opravit případnou chybu v konfiguračním souboru je jednou z největších výhod zavaděče GRUB.


Poznámka Pro bezdiskové zavádění je ale vhodnější použít zavaděč, který umožňuje zavádět jádro přes PXE, např. PXELINUX. GRUB2 sice také umí použít PXE, ale bohužel pouze pro bezdiskové zavedení potřebných modulů pro zavedení lokálního systému.
Upozornění Pokud se používá pro zavádění BIOS je třeba hlídat aby:
  1. sahal při zavádění na správné zařízení
  2. použité disky ve stroji neměly v MBR nějaké zbytkové záznamy, které by mohly zmást BIOS
  3. byla po aktualizaci zavaděče aktualizována také část, která je uložena na blokovém zařízení, odkud ji načítá BIOS

Chybí-li ovladač v jádře zavaděče, potřebný pro zpřístupnění souborového systému se zbývajícímu moduly, pak nelze problém vyřešit jinak, než pomocí zavedení prostřednictvím jiného zavaděče a nebo opravou záznamu na blokovém zařízení přes chroot z prostředí linuxového live CD.

Zavedení jádra

Zavaděč si lze představit jako jednoúčelový operační systém, který má za úkol:

  1. rozbalit jádro operačního systému do paměti počítače..
  2. spustit ho..
  3. ..a přitom mu předat případné parametry.

Jádro je spustitelný binární soubor, který poběží - na rozdíl od zavaděče - po celý čas běhu operačního systému.

Zavaděč jádro z úložiště přebírá ve formě samorozbalovacího archívu, jehož jméno podle obvyklého úzu začíná řetězcem vmlinuz. Toto pojmenování je závazné pouze do té míry, aby ho pod ním zavaděč v úložišti našel.

Jádro se rozbalí do paměti a od zavaděče převezme případné konfigurační volby. Pak se pokusí identifikovat a připojit zařízení, na kterém má být uložen operační systém a z něj spustit spouštěč dalších procesů - init. Aby to bylo možné, musí mít k dispozici všechny potřebné ovladače. Aby se jádro obešlo bez ramdisku, musí mít v sobě tyto ovladače zakompilované na tvrdo.

U distribucí, které si kompilují jádro na míru podle aktuální konfigurace stroje, s tím obvykle není problém. Ovšem u distribucí, které mají mít univerzální použití, by optimální konfigurace takového jádra mohla představovat neřešitelný problém. Proto se u nich využívá při zavádění tzv. RAM disk.

Monolitické jádro
Nepotřebuje ramdisk protože je kompilované na míru a obsahuje pouze potřebné ovladače. Má výhodu v tom, že může být lépe optimalizované a tím pádem i o něco výkonnější.
Modulární jádro
Nemusí využívat ramdisk, pokud má potřebné ovladače k dispozici. Výhoda ramdisku je však v tom, že mu stačí pouze základní ovladače potřebné pro rozbalení a připojení ramdisku. Ostatní ovladače jsou uloženy ve formě jaderných modulů v ramdisku a do jádra se zavádějí pouze v případě že jsou zatřebí. Takové jádro je tedy mnohem více flexibilní z hlediska diverzity hardware.


Prostředí RAM disku

Je čistě technicky vzato další kus operační paměti (odtud RAM disk), kam si jádro vybalí z komprimovaného cpio archívu minimalistické linuxové prostředí. Jádro s ním pak pracuje jako by šlo o normální systémový disk. Tzn. že si jej připojí, a spustí z něj init.

V tomto případě však nejde o binární spouštěč procesů, ale shellový skript, který postupně spouští další skripty. Z hlediska zavádění systému je podstatné, že skript init obsahuje podmínky, které umožňují proces zavádění cíleně přerušit.

K takovému přerušení zaváděcího procesu obvykle dojde, když některý ze spouštěcích skriptů vrátí chybu.

Prostředí a nástroje v ramdisku, umožňují zjistit příčinu chyby a případně provést její opravu. Někdy ale může být v okamžiku selhání příliš pozdě na to zjišťovat kde je problém, proto je dobré vědět:

  1. Jak cíleně přerušit zaváděcí proces v určité fázi zavádění.
  2. Co všechno lze v prostředí ramdisku dělat.
  3. Jak rozbalit obsah ramdisku, resp. vypsat jeho obsah.
  4. Jak dostat do ramdisku chybějící jaderné moduly
  5. Jak přidat do ramdisku další užitečné nástroje
  6. Jak přidat do ramdisku vlastní zaváděcí skript
  7. Jak restartovat stroj z prostředí ramdisku

Přerušení zaváděcího procesu

Přerušení zaváděcího procesu lze záměrně docílit tím, že se přes zavaděč předá jádru před jeho zavedením volba break.

vmlinuz... break=premount ...

Že jsme v prostředí ramdisku se pozná tak, že se místo obvyklého přihlášení rovnou objeví textová konzole

(initramfs)

Pokud konzoli opustíme příkazem exit, bude zaváděcí proces dál pokračovat.

Poznámka Skript init, který je v kořeni ramdisku, se generuje na základě konfigurace v souboru /etc/initramfs-tools/initramfs.conf při sestavení souboru initrd. Ostatní skripty, které má ramdisk v adresáři /scripts. Se při jeho sestavení, či aktualizaci kopírují z adresáře /etc/initramfs-tools/scripts.

top

Parametr #top přeruší zaváděcí proces před spuštěním prvního skriptu. Jediná operace, která se realizuje dřív, je načtení obsahu paměti z disku, pokud byl systém při předchozím spuštění uspán na disk.

Během této fáze jádro provádí inicializaci existujících fyzických zařízení. Ty se přitom ohlašují svým specifickým kódem, na jehož základě jádro provádí identifikaci a natažení příslušného ovladače.

Protože k zařízení může existovat více ovladačů, které pochopitelně nelze používat současně, je součástí ramdisku adresář /etc/modprobe.d, s konfiguračními soubory k jaderným modulům, ve kterých může být použití konfliktních modulů zakázáno.

Může se však vyskytnout situace, kdy některý z automaticky natahovaných modulů obsahuje chybu, která vede ke hroucení jádra. Pro takové případy akceptuje jádro seznam zakázaných modulů předaný zavaděčem prostřednictvím volby blacklist

vmlinuz... blacklist="xfs jfs ceph" ...

I když pak může být do určité míry systém omezen, můžeme jej dostat do stavu kdy se dá problém vyřešit.

Poznámka Tabulka, podle které jádro provádí tuto identifikaci se generuje před(!) sestavením, či aktualizací ramdisku příkazem depmod

modules

Parametrem #modules se přeruší zavádění předtím, než init zavolá funkci load_modules. Ta zavede do jádra další moduly, které nemusí být bezprostředně vázané na konkrétní hardware, ale mohou být nezbytné pro další zavádění systému.

Seznam těchto modulů může být uložen rovnou v ramdisku - soubor /conf/modules, ale také předán jádru prostřednictvím zavaděče

vmlinuz... modules="aufs reisefs" ...

premount

Kromě jaderných modulů a skriptů, které řídí zaváděcí proces, obsahuje ramdisk také nástroje a utility, co umožňují zavést systém ze sdíleného NFS adresáře, sestavit RAID pole, nahodit LVM skupinu, používat kryptovaný souborový systém, opravit poškozený souborový systém aj.

V této fázi tedy probíhají přípravy na to, aby ho bylo možné připojit zařízení kterém je uložen systém.

Poznámka Protože v tomto bodě vzniká při zavádění nečastěji problém, je parametr #premount výchozím pro volbu break, je-li uvedena bez parametru.

mount

Cestu k zařízení, na kterém má být uložen zaváděný systém, jádru předává zavaděč jako parametr volby root.

vmlinuz... root=/dev/sda1 ...

Skript init hodnotu /dev/sda1 uloží do proměnné ${ROOT}, která se před přepnutím do finálního systému zruší. V prostředí ramdisku si lze vypsat přes echo.

Během předchozí fáze mělo být zařízení připraveno a nyní se ho init pokusí připojit. Pokud se mu to nedaří, umožňuje přerušení ve fázi #mount zjistit proč.

Nejprve je třeba zkontrolovat obsah proměnné ${ROOT}. Jeví-li se v pořádku, je třeba zjistit, zda-li příslušné zařízení skutečně existuje.

Pokud ne, tak to může znamenat že..

  • jádru chybí potřebný ovladač (po kompilaci modulu nebyl aplikován depmod a zaktualizován příslušný ramdisk)
  • nebo došlo k přejmenování zařízení (kupř. po přidání dalšího blokového zařízení do počítače, či při změně pořadí diskových oddílů)
  • nebo z nějakého důvodu nedošlo k sestavení příslušného blokového zařízení (v případě RAID pole či LVM skupiny)
Poznámka Některé zavaděče, jako např. GRUB, umožňují parametr volby root změnit ještě před spuštěním zaváděcího procesu, ale jsou situace, kdy to udělat nelze a je třeba úpravu provést v ramdisku.
Upozornění Jednou z příčin, proč se nepodaří zařízení připojit, může být poškozený souborový systém. Proto musí být součástí ramdisku také nástroje, které ho umožňují opravit.

Pokud v něm chybí, pak to znamená, že je během sestavení ramdisku neměl systém k dispozici.

V takovém případě je třeba nejprve souborový systém opravit jiným způsobem. A pak přes chroot provést aktualizaci ramdisku

bottom

Většinu souborových systémů nelze opravit, pokud se s nimi pracuje. Systém uložený v ramdisku je tak ideálním prostředím pro takové operaci, protože

init

Na závěr přepne do finálního systému a spustí z něj /sbin/init

Konfigurace sítě

Konfigurace síťového rozhraní je u bezdiskového systému základním předpokladem pro úspěšné namountování systémového disku. Provádí ji podle parametrů předaných jádru skript /scripts/nfs během fáze mount - těsně předtím, než se pokusí o namountování o systémového disku vypublikovaného přes NFS server.

Selhat může z následujících příčin:

  • chybí ovladač síťového rozhraní
  • síťové rozhraní je připojeno do subnetu, který nemá přístup na NFS server
  • Pro IP adresu klientské stanice není do adresáře na NFS serveru povolen přístup
  • V konfiguraci síťové karty, nebo v cestě ke vzdálenému adresáři je chyba

Debug ramdisku

vmlinuz... debug ...

Úpravy ramdisku

Pro práci s ramdiskem jsou určeny nástroje z balíku initramfs-tools. Ale lze si poradit i bez nástrojů z tohoto balíku - pomocí běžně dostupných systémových utilit.

Výpis obsahu ramdisku

Pro výpis obsahu ramdisku lze použít nástroj lsinitramfs. Pokud ale není k dispozici, stačí vědět, že ramdisk je v podstatě pouze zkomprimovaný cpio archív

zcat /boot/initrd.img-3.2.0-2-686-pae | cpio -t

Rozbalení ramdisku

Pokud si chceme důkladněji prozkoumat obsah ramdisku, tak si ho můžeme vybalit do samostatného adresáře

zcat /boot/initrd.img-3.7.7 | cpio -i

Zabalení ramdisku

Po případných úpravách ho pak zase můžeme zabalit - pro jistotu do nového souboru

find . | cpio -o -H newc | gzip > /boot/initrd.img-3.7.7-upraveny

Korektní sestavení ramdisku u Debianu

Výše uvedené postupy je dobré znát, ale pro korektní sestavení ramdisku je rozumnější používat nástroj update-initramfs z balíku initramfs-tools. Ten totiž zajistí - na základě konfigurace - aby sestavený ramdisk obsahoval vše potřebné i po každé aktualizaci, bez toho, že by bylo nutné pokaždé vytvářet či upravovat prostředí ramdisku ručně.

Ostatně stejný nástroj se volá i při instalaci nového jádra.

Konfigurační soubory a skripty spojené se sestavením ramdisku, se v systému vyskytují na třech místech:

  1. Adresáře v /etc/initramfs-tools jsou určeny pro uživatelskou konfiguraci
  2. Do adresáře /usr/share/initramfs-tools umísťují své skripty instalační balíčky
  3. A do adresáře /var/lib/initramfs-tools se ukládá kontrolní součet (realizovaný přes shasum ) ramdisku sestaveného pomocí initramfs-tools


kmod - se stará o načítání jaderných modulů v ramdisku

  1. načte shellový skript /hook-functions (používá funkce zde uvedené)
  2. zavolá funkci copy_exec, (která udělá co?)
  3. zkopíruje nástroje modprobe a rmmod
  4. se stará o include jaderných modulů.

udev -

Struktura konfiguračních adresářů pro sestavení ramdisku

/conf.d /hooks /scripts /init-bottom /init-top

initramfs.tools modules update-initramfs.tools

Upozornění Od jádra verze >= 3.5 je modul nfs rozdělen na více modulů

Reboot z prostředí ramdisku

echo b > /proc/sysrq-trigger

Monitoring

Lokální přesměrování konzolového výstupu

vmlinuz... console=ttyS0 ...

Síťové přesměrování konzolového výstupu

Pokud má jádro zakompilovaný modul netconsole, lze výstup přesměrovat po síti.

vmlinuz... netconsole=6665@[IP stanice]/[síťové zařízení],6666@[IP vzdálené stanice]/[MAC síťového rozhraní vzdálené stanice]

Na vzdálené stanici ale musí na příslušném portu naslouchat aplikace. Použít lze kupř. utilitu nc

nc -u -l -p 6666