Výpisy z jádra
Výpisy z jádra slouží k informování uživatele o událostech probíhajících v jádře. Chovají se velmi podobně jako standardní výstup, byť s drobnými odlišnostmi. Díky tomu mohou být snadno využity i pro ladění kódu ovladačů.
Jádro zaznamenává výpisy do kruhového bufferu, odkud jsou postupně vyčítány démonem klogd nebo syslogd a ukládány do souboru /var/log/syslog.
Na vyžádání si můžeme obsah bufferu vyčíst a případně i smazat příkazem dmesg. Nejčastěji se používá tento příkaz ve spojení s příkazem tail, který vytiskne 10 posledních záznamů (i více, větší hodnotu lze zadat jako parametr).
Příklad:
$ dmesg | tail
Právě výpisy z ovladače spolu s pomocí příkazu dmesg slouží jako velmi jednoduchý, ale přitom ve většině situací dostačující nástroj k ladění funkcionality ovladačů.
Kromě bufferu může jádro směřovat své výpisy i přímo na systémovou konzoli. Systémovou konzolí se nemyslí virtuální terminál představovaný programem xterm v X windows, ale skutečně systémová konzole, na kterou se zobrazují např. zprávy při nabíhání systému. Ve většině distribucí je dostupná přes kombinaci kláves Ctrl+Alt+F1.
Výpisy z jádra mají několik logovacích úrovní dle závažnosti. Je jich osm a jsou určeny hodnotami 0 - 7. 0 přísluší té nejzávažnější (ta poslední, kterou bychom měli ignorovat), 7 pak té nejméně závažné. Logovací úrovně a jim odpovídající symbolické konstanty jsou v souboru <linux/kernel.h> definovány takto:
#define KERN_EMERG "<0>" // system je nepouzitelny #define KERN_ALERT "<1>" // kriticka chyba, zasah vyzadovan ihned #define KERN_CRIT "<2>" // kriticka chyba #define KERN_ERR "<3>" // bezna chyba #define KERN_WARNING "<4>" // varovani #define KERN_NOTICE "<5>" // vyznamne sdeleni #define KERN_INFO "<6>" // bezna informace #define KERN_DEBUG "<7>" // ladici informace
My budeme nejčastěji využívat úroveň KERN_ERR pro chyby typu selhání alokace paměti, nekomunikující zařízení apod., pak úroveň KERN_WARNING pro nepodstatné chyby (divná hodnota proměnné), dále úroveň KERN_NOTICE pro sdělení typu úspěšná detekce zařízení a úroveň KERN_INFO pro hlášení typu změna nastavení zařízení apod. Úroveň KERN_DEBUG můžeme používat hojně pro ladící účely, protože se zprávy s touto úrovní budou vypisovat jen tehdy, když je jádro sestaveno s podporou ladění.
Logovací úrovně výpisů jádra nabízí snadný způsob filtrace výpisů a to jak pro démona klogd, resp. syslogd, tak i pro zobrazování výpisů na systémové konzoli.
Nastavení, které úrovně se budou zobrazovat na systémové konzoli, najdeme v souboru /proc/sys/kernel/printk. Zde jsou dostupné čtyři hodnoty, z nichž nás zajímá jen ta první - console_loglevel, protože výpisy s vyšší hodnotou než udává tato hodnota (dle závažnosti, nikoliv dle číselné hodnoty), jsou zobrazeny na systémové konzoli. Výchozí hodnota console_loglevel je 4, takže výpisy s úrovněmi KERN_EMERG až KERN_ERR jsou ve výchozím nastavení zobrazeny vždy.
Změnu hodnoty console_loglevel v souboru /proc/sys/kernel/printk provedeme snadno:
$ echo 8 > /proc/sys/kernel/printk
Po tomto nastavení budou na systémové konzoli zobrazovány výpisy jádra ze všech logovacích úrovní včetně KERN_DEBUG (pokud ovšem bylo jádro sestaveno s podporou ladění).
Funkce printk
Výpis jádra vytvoříme z modulu voláním funkce printk() definované v <linux/kernel.h>. Tato funkce je velmi podobná svému protějšku z uživatelského prostoru funkci printf(). Používá dokonce i stejné formátovací řetězce. Jedinou odlišností je právě parametr, který určuje logovací úroveň daného výpisu.
Příklad:
printk(KERN_ERR "Detecke zarizeni selhala. Chyba(%d)\n", kodChyby);
Zkušené programátory překvapí, že logovací úroveň není od ostatních parametrů oddělena čárkou. Ano, je to tak a je to správně. Komu to ovšem nedělá dobře (zvyk je zvyk, že), může čárku za logovací úroveň uvádět, chybou to není.
A nebyli by to vývojáři jádra, kdyby k pohodlné práci s funkcí printk() nepřidali i pár maker:
// nahrada printk s urovni KERN_ERR pr_err("Detekce zarizeni selhala. Chyba(%d)\n", kodChyby); // dalsi makra viz <linux/kernel.h> pr_info("Jsem tvuj ovladac\n"); pr_debug("Padam, tedy jsem\n");
Tato makra jsou definována pro všechny úrovně a najedeme je v hlavičkovém souboru <linux/kernel.h>.