Linux Kernel
Obsah
- Změny v tomto dokumentu
- Historie
- Současnost
- Verze jádra, patchování
- Konfigurace
- Překlad, instalace
- Krátké shrnutí
- Dokumentace
- Bugzilla, LKML
- Časté chyby
- Ostatní jádra
- Odkazy
- Jak to funguje
Historie dokumentu
- 06.01.2007 – ach ty hrubky
- 14.08.2006 – oprava spousty faktických chyb
- 27.06.2006 – drobné úpravy, zakomponování do stránek, obsah je nyní validní xhtml
- 28.05.2006 – komentář k /proc/config.gz
- 22.05.2006 – NetBSD odkaz aktualizován, upravena poslední sekce
- 30.12.2005 – přidána sekce změny, doplněna a poopravena část o NetBSD
Historie
Linus Torvalds napsal linux 0.01 v roce 1991 se slovy:
Hello everybody out there using minix - I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones.
Od té doby se linux změnil, stal se velkým a profesionálním pro nejen x86 mašiny, do dnešní podoby – linux řady 2.6, o které je tento referát.
Jedna z verzí vzniku jména linux (ISBN 0-7382-0333-5):
“Linux was my working name,” Linus says, “but if I actually used it as the official one, people would think that I was an egomaniac and wouldn't take it seriously. So I chose this very bad name: Freax” - free + freak + x. “Sick, I know.” Ari Lemmke, who ran the FTP site (myslí se funet.fi), decided he didn't like the Freax label, so he used the working name instead.
Trvalo dlouhou dobu, než vznikla 1. opravdu multiplatformní, funkční řada 2.x.
Současnost
Nynější jádra jsou číslována trochu odlišně od starších, nedávno doznalo číslování malých změn. Ještě na začátku května popisoval číslování Linus takto:
- 2.6.<even>: even at all levels, aim for having had minimally intrusive patches leading up to it (timeframe: a week or two)
- 2.6.<odd>: still a stable kernel, but accept bigger changes leading up to it (timeframe: a month or two).
- 2.<odd>.x: aim for big changes that may destabilize the kernel for several releases (timeframe: a year or two)
- <odd>.x.x: Linus went crazy, broke absolutely _everything_, and rewrote the kernel to be a microkernel using a special message-passing version of Visual Basic. (timeframe: "we expect that he will be released from the mental institution in a decade or two").
Dnes si ale můžete v archivu jader všimnout, že existují i verze 2.x.y.z, kde z je nějaké malé číslo. Takové verze obsahují malé změny, které bylo nutné opravit například kvůli funkčnosti. Souběžně jsou vytvářeni kandidáti na další uvolnění celku – 2.x.(y+1)-rcz jádra. Po dostatečném testování se uvolní jádro 2.x.(y+1) a dále zase jeho podverze a -rc na další verzi.
Stažení, dekomprimace archívu
Nejnovější jádra lze získat z odkazů kernel.org. Od doby vzniku po současnost se vytvořilo mnoho obrazů primárního ftp serveru, odkud je možné jádro získat, mezi ně patří i naše fakulta, na adrese ftp.muni.cz, resp. ftp.linux.cz. Další možností je použít rsync a git/cogito (můžu doporučit, jsou to nástroje typu CVS, SVN).
Po stažení jádra jej můžeme dekomprimovat standardní cestou:
tar jxf linux-verze.tar.bz2
která nám vytvoří v pracovním adresáři adresář s rozbaleným, novým, jádrem.
Verze jádra, patchování
Tím, že jsme stáhli a rozbalili jádro, máme vanilla verzi, kterou vydává Linus a má číslovaní popsané výše. S malým zpožděním se k vanilla jádrům (a jejich -rc) vydávají patche, které spravují různí lidé. Mezi nejpoužívanější mezi kernel hackery patří -mm jádro vydávané Andrew Mortonem (akpm@osdl.org). Další je -ac vydávané chlapíkem s červeným (RedHat) klouboukem, Alanem Coxem. Mezi ty méně známé patří -gh (nebo -gk?), které vydává Greg Kroah-Hartmann a další (-ck, -rt, …).
Důležité jsou také -git patche, což jsou snapshoty z git databáze, ve které se jádro vyvíjí.
Pokud chcete nebo potřebujete nějaký patch, stáhněte jej, rozbalte a změňte pracovní adresář do jádra, na jehož verzi se dá patch aplikovat. Poté stačí:
patch -p1 -i <cesta k patchi>
Patche na vanilla jádra se aplikují na poslední 2.x.y stabilní verzi před
patchem. Pokud si nejste jisti, na co se dá patch aplikovat, je nejlepší
spustit něco podobného jako
grep '+++ b/Makefile' -A10 patch. Řádky začínající
- jsou stará verze, + potom nová (kterou známe z názvu patche).
Nezapomínejte, že patch(1) má parametr --dry-run.
Konfigurace
make help
vidět, je možné využít několik rozhraní pro
konfiguraci. To nejjednodušší je textové (make config), kde
odpovídáte na otázky stiskem y,
n, m nebo ? pro nápovědu. Další, textové, tentokrát ale s výběrem v menu je
make menuconfig
make xconfig nebo make gconfigJak nastavit nové jádro?
To je asi nejčastější otázka, kterou není lehké
zodpovědět. Nejlépe je najít konfigurační soubor odpovídající mé konfiguraci,
tedy aspoň přibližně, někde na Internetu (nejčastější zbůsob tvorby jádra pro
notebooky, kde jsou konfigurace u jednotlivých modelů podobné). Pokud je
hledání takové konfigurace neúspěšné, přijdou na řadu nástroje, z nichž lze
současně používané ovladače vyčíst. Jednak můžeme zjistit aktuálně načtené
moduly pomocí lsmod(8), jednak využijeme výstup
dmesg(8) současného jádra, v neposlední řadě můžeme zjistit typ
HW pomocí lspci(8). Není dobré kopírovat konfiguraci
z distribučních jader. Systém sice bude fungovat, ale jádro bude obrovské
a téměř všechny ovladače se vytvoří jako moduly, což může být nežádoucí.
Pokud již známe konfiguraci, stačí vybrat v konfigurační utilitě
odpovídající ovladače. Není na škodu si konfiguraci uložit do adresáře s
vytvořým jádrem, do /boot pro pozdější kompilaci novějšího jádra.
Tím se nepřímo dostáváme k dalšímu make-cíli kompilace:
make oldconfig
který provedeme po upgradu jádra, popřípadě po jeho patchování. Konfigurátor
se zeptá pouze na rozdílné volby, ty stejné použije z předchozího konfiguračního
souboru .config, který se hledá buď v adresáři se zdrojovými
kódy, nebo v adresáři nastaveným pomocí O=.
V neposlední řadě je třeba zmínit možnost O=<cesta>, čímž řekneme překladači, aby adresář se zdrojovými kódy zůstal nezměněn, naproti tomu, vše potřebné ke kompilaci a vytvoření výsledného obrazu se bude ukládat do <cesta>.
V adresáři je také možné provést
make clean nebo make mrpropercož vyčistí náš strom od přeložených věcí, v
druhém případě i s konfiguračím souborem. Ve starších verzích jádra bylo nutné
spouštět clean prakticky před každou kompilací. V jádře 2.6 jsou závislosti
vyřešeny daleko lépe a nutné to (v 97,283 %) není. Minulostí je také
make dep, který řešil závislosti ve starých jádrech.
Konfigurační řádka může tedy vypadat takto:
make menuconfig
mkdir ../xyz && make O=../xyz xconfig
Module or not to module?
Modul je soubor s příponou .ko, do jádra se vloží
příkazem insmod(8) s cestou, popřípadě sofistikovanějším
modprobe(8), který nahraje i moduly, na kterých ten námi
požadovaný závisí (zkusme prozkoumat
/lib/modules/`uname -r`/modules.*, vytvořili je při překladu
module-init-tools). Po úspěšném vložení běhají bity těchto
binárních souborů
mezi ostatními jadernými, tedy v kernelspace. To mimo jiné značí, že mohou
představovat bezpečnostní riziko. Vždy přemýšlíme nad tím, od koho modul je a
jak moc tomu
člověku věříme! Rootkity může útočník docílit takřka čehokoliv, o čem se nám
raději nechce ani zdát (totální nadvláda nad systémem i HW). Z tohoto důvodu
říkáme v produkčních nasazeních modulům raději NE.
Jinde se jako modul doporučuje překládat ovladače nepříliš
často používané, např. wi-fi, floppy, usb-storage…
Po odstranění závislostí (např. zastavením síťového rozhraní, odmountováním
disku) odebereme modul příkazem rmmod(8).
modinfo(8) vypisuje informace o modulu včetně možných parametrů,
pokud ovšem modul takovéto informace obsahuje.
Významné volby nastavení
Při samotné konfiguraci je žádoucí (ne vždy nutné k běhu; generic drivery sice fungují, ale bez HW akcelerace) vkládat do jádra ovladače odpovídající přímo dedikovanému HW.
-
General setup
- Local version – text, který se může zobrazovat při výpisu uname
- Auditing support – distribuce auditování většinou podporují
- Kernel .config support – přidat do souboru jádra jeho
konfiguraci (extrakce pomocí
scripts/extract-ikconfig) - Enable access to .config through /proc/config.gz – nedoporučuji zapínat tuto volbu, odeberete si zbytečně volné místo z neswapovatelné paměti jádra (raději uložte konfiguraci přímo do /boot/config<-verze>)
-
Loadable module support
- Enable loadable module support – zapíná podporu modulů
- Module unloading – zapíná podporu
rmmodpro moduly
-
Processor type and features – nastavení smp, paměti a vše, co se
točí kolem procesoru(ů)
- zde je nezbytné vybrat správnou architekturu a procesor
- Symmetric multi-processing support – smp, podpora vícejaderných pprocesorů
- Preemption Model – preemptivní jádro, v podstatě méně stabilnější, rychlejší odpovědi jednotlivým procesům (snížení stárnutí atd.), desktop yes, server no, většinou
- High Memory Support – aby se využívala všechna pamět v systému, je třeba si rozmyslet, kterou volbu vybrat
- Timer frequency – ovlivníte rychlost odpovědi systému na události
-
Power management options
- ACPI nemusí na starších (dnes spíše výjimka) strojích fungovat. Někdy je nutné ho vypnout, a zkusit štěstí s APM. Pokud ale váš systém ACPI podporuje a funguje s ním, nepokoušejte se jej vypínat, ACPI totiž není jen power managment, ale umí předávat paremetry a konfiguraci systému, nebo jej řídit.
- Frequency scaling – podpora jádra pro změnu frekvence procesoru za chodu (výdrž bateríí)
-
Bus options – nastavuje, jaké sběrnice chcete zakompilovat, na
tomto výběru poté záleží, zda se vám zobrazí ovladače, které jednotlivé
sběrnice vyžadují
- PCI access mode – za zmínku stojí, že většina PCI BIOSů má bugy a někdy nedokáže s jádrem spolehlivě pracovat, v tom případě je třeba nastavit Direct
- ISA support – některé senzory fungují jen přes ISA sběrnici
- PCCARD (PCMCIA/CardBus) support – podpora PCMCIA a 32bit CardBus
-
Executable file formats – nastavení podpory pro spustitelné
formáty
- Kernel support for ELF binaries – podpora standardního formátu Linuxu, v 99 % je podpora zapnutá
- Kernel support for MISC binaries – tento formát vykonávaný mostem přes jádro v uživatelském prostoru využije například wine k simulaci PE EXE (windows) spustitelných souborů
-
Networking – nastavení sítě, firewallu a všeho síťového, kromě
ovladačů
- Networking options
- TCP/IP networking – nastavení IPv4 a IPv6; IP: Virtual Server Configuration, pokud chcete IPVS, distribuci zátěže na více serverů
- Network packet filtering – firewall pro IPv4 a IPv6
- QoS and/or fair queueing – omezování provozu a řazení paketů
- Ostatní – nastavení IrDA, Bluetooth…
- Networking options
-
Device Drivers – ovladače, zde se podle závislostí na předchozím
nastavení zobrazují ovladače, které můžete vybrat ke kompilaci
- Block devices, ATA/ATAPI/MFM/RLL support a SCSI device support – nastavení blokových zařízení a disků. SATA již nadále není v nabídce SCSI, nýbrž samostatně. SCSI vrstvu vyžaduje usb-storage (flash disky apod.), pakliže nepoužijete ub ovladač, který SCSI vrstvu nepotřebuje.
- Network device support – nastavení síťových zařízení
- Character devices – zde jsou mimo jiné grafické ovladače
- I2C support a Hardware Monitoring support – nastavení senzorů
- Graphics support – frame buffer je výhodný, pokud často pracujete v konzoli bez X a nevyužijete volbu vga= jako parametr jádra. Také grafické spouštěče (např. rhgb) vyžadují frame buffer. Bez něj ale může být start systému rychlější, proto já osobně doporučuji vypnout.
- Sound – v dosavadní době dosluhující systém OSS bude v brzké době odstraněn, volte ovladače ALSA
- USB support – USB od polohovacích zařízení po disky
-
File systems
- Second extended fs support – ext2 s ACL volbou
- Reiser4 – tento fs ukládá i soubory do stromu
- XFS – povětšinou serverový systém, umí pracovat ve více vláknech
- Quota support – podpora kvót
- Kernel automounter support – podpora autofs (automount)
- Pseudo filesystems – zde je kromě jiného procfs
- Native Language Support – podpora znakových sad v jádře
-
Kernel Hacking
- SysRq – bych doporučil zapnout, může vám pomoct, když je systém v nesnázích. Nedoporučuji ho ovšem aktivovat (zapsat 1 do /proc/sys/kernel/sysrq, viz Documentation/sysrq.txt) na počítačích přístupných i neznámím lidem
- Security options – pokud používáte více bezpečnostních modelů, je tohle sekce pro vás (NSA SELinux a další volby)
Možnosti, u kterých si nejste jisti ani po přečtení nápovědy, ponechte nastavené tak, jak radí v nápovědě (např. If unsure, say N.).
Přeji příjemně strávené hodiny u konfigurace, neboť to je většinou věc, která trvá na svém prvním jádře nejdéle.
Překlad, instalace
To první je věc jednoduchá na provedení, složitější na čas. Pro překlad v podstatě stačí příkaz
make <O=…> all modules_install
all znamená přeložit vše, tedy vytvořit obraz i moduly (viz
make help|grep ^*).
modules_install zkopíruje moduly
do /lib/modules/x/ a vytvoří závislosti. x vyjadřuje verzi jádra, v novějších
jádrech může také obsahovat řetězec popisující aktuální snapshot z databáze.
Tím jsme odbyli i první fázi instalace – moduly. Nyní je třeba nastavit systém tak, aby akceptoval a spustil naše nové jádro. Důležité je nakopírovat jádro tam, kde ho bude moci přečíst námi používaný zavaděč. Na většině systémů by to měl být adresář /boot. Provedeme tedy něco jako
cp <`…' z O=…>/arch/<naše architektura>/boot/bzImage /boot/<cokoliv>
kde cokoliv je
většinou vmlinuz-<verze jádra>, avšak např. vyznavači powerpc mají raději
vmlinux-<verze>. Dále je nutné upravit konfiguraci
zavaděče a pokud budeme chtít použít initramdisk, tak vytvořit i jej pomocí
mkinitrd(8), pidinávod
zde.
Celý proces instalace za nás může udělat /sbin/kernelinstall, který spustíme
pomocí make <O=…> install, pokud ho distribuce
obsahuje.
To je celý proces, po rebootu by mělo jádro fungovat (v některých případech nebude, čtěte časté chyby).
Parametry jádra
Některé nedostatky/přebytky lze doladit parametry jádra, jejichž neúplný výčet
je v Documentation/kernel-parameters.txt. Pro přesný výčet je nejlepší se vždy
podívat do zdrojových kódů (i v případě, že vám nějaký parametr nefunguje).
K těm základním patří root=, init=, ro, rw, které po řadě nastavují kořenový
svazek, program, který se má spustit jako init, mountování kořenového svazku
jen pro čtení a pro zápis v ranné fázi, distribuční skripty popř. později
provedou přemountování do rw.
System.map
Je soubor, který se kopíruje také do /boot a neobsahuje nic jiného, než
tabulku převádějící adresy na symboly. Neslouží ani tak samotnému jádru, jako
spíše uživateli, nebo jemu používanému debuggeru.
Ve většině případů je System.map linkem na nějaký System.map-verze.
Na dobře nastaveném jádře by kompilace neměla přesáhnout půl hodiny (v
závislosti na procesoru, samozřejmě). Nezapomínejte na přepínač -j, který
umí make(1).
Krátké shrnutí
verze=2.6.13 # například wget ftp://ftp.muni.cz/pub/linux/kernel/v2.6/linux-$verze.tar.bz2 tar jxf linux-$verze.tar.bz2 mkdir build cd linux-$verze make O=../build menuconfig make O=../build -j3 all make O=../build modules_install cp ../build/arch/i386/boot/bzImage /boot/vmlinuz-verze vim /boot/grub/menu.lst # přidat záznam a nahradit LABEL= /dev/... # mount --move ... [viz časté chyby], pokud je třeba reboot
Dokumentace
Soubory s dokumentací jsou umístěny v adresáři Documentation
jádra. Nachází se zde i soubor 00-INDEX, ve kterém je stručný
popis (téměř) všech souborů z tohoto adresáře.
Pro zasvěcenější stojí za zmínku ManagementStyle, CodingStyle (ten je pro
všechny, každý správný céčkař by se měl těmito radami řídit),
SubmittingDrivers a SubmittingPatches. Dále je možné generovat DocBook
nápovědu k API, která je stále ve vývoji, takže spousta věcí chybí, tak, že
zadáte make htmldocs (xmldocs, psdocs, pdfdocs, mandocs). V
adresáři Documentation/DocBook by poté měly být vygenerované
soubory s příponou, kterou požadujete.
Bugzilla, LKML
Jako každý rozsáhlý projekt, i Linux má své vši. Pokud se vám podaří na nějakou přijít, nebo lépe, vyřešit ji, podělte se s ostatními. Bugy můžete zadávat na bugzilla.kernel.org, což je všeobecně známý, ucelený systém na bugtracking. Popřípadě můžete poslat patch, který vyhovuje CodingStyle na linux-kernel@vger.kernel.org s CC lidem, kteří mají odpovídající úsek na starost (viz MAINTAINERS v adresáři jádra), popřípadě na akpm, pokud není možné nalézt odpovídající osobu (ovladač není pod správou).
Časté chyby
Některé distribuce mají vanilla jádro upravené tak, aby fungovaly některé specifické věci:
Vanilla jádro nepodporuje LABEL pro nastavení kořenového
svazku v zavaděči. Tuto vymoženost obstarává initramdisk. Pokud
ji chcete využít, musíte si initrd vytvořit, nechcete-li jej nutné v
zavaděči nastavit konkrétní /dev/[hs]d* svazek.
Jádro skončí s chybou nemožnosti namountovat svazek. (hned po zavaděči) Někdy je příčína v tom, že udev vytváří speciální soubory až je jádro načtené (protože je to user-level démon), ale některé programy (/sbin/init) před tím potřebují /dev/console a /dev/null. V tom případě je nutné tyto soubory vytvořit ručně:
mkdir /tmp/dev mount --move /dev /tmp/dev # finta jádra 2.6 cd /dev mknod initctl p mknod console c 5 1 mknod null 1 3 mknod zero 1 5 for cnt in 0 1 2 3 4 5 6 7 8; do mknod tty$cnt c 4 $cnt done
V /dev by se měly objevit speciální soubory, které jsme vytvořili a můžeme
přesunout udev dev zpět do /dev příkazem mount --move /tmp/dev
/dev.
Jádro skončí s chybou nemožnost namountovat kořenový svazek. (těsně před načtením a spuštěním initu) Většinou jste zapomněli dát nějaký ovladač přímo do jádra. Pokud nepoužíváte initramdisk, musí být filesystém kořenového svazku, ovladač řadiče disku a ovladač chipsetu v jádře! Zkuste číst generovaný text při startu systému, jestli opravdu jádro našlo váš disk.
Některé z těhto věcí jsem zachytil na diskuzích před delší dobou, zdroje už bohužel nevím (je možné, že zdrojem byly i stránky Fedory).
Ostatní (nelinuxová) jádra
Zkompilovat na míru lze i jiná jádra. Např.
NetBSD,
FreeBSD (ssys.*).
NetBSD se konfiguruje editací textového souboru, pomocí utility
config(8) se vytvoří adresář, ve kterém se překládá –
spustí se make depend a make. Utilita config musí
odpovídat verzi jádra, nedávno (kolem verze 3.0 final) se začala objevovat v
balíku s jádrem a ne s ostatními zdroji jako tomu bylo předtím. Hotové jádro se
uloží do
souboru netbsd, který lze bootovat jako kernel ze zavaděče. [pro získání
představy, jak to chodí v jiných jádrech].
Odkazy
kernel.org – domovská stránka jádra
Linuxu
fakultní zrcadlo
mkinitrd
– jak na to
Linux Device Drivers – kromě
toho, jak psát ovladače jsou zde dobré připomínky a páky, které lze na jádro
použít
Podobných návodů je na Internetu jistě spousta, já jsem se pokusil zachytit mé zkušenosti, které doufám pomohou. Přeji hodně štěstí při kompilaci jader.
A jak to všechno funguje? (jen tak na okraj)
Téměř v každém adresáři je soubor Makefile, jako v každém
projektu. Před samotnou konfigurací jádra se zkompiluje vámi zadaný
konfigurátor nad TUI/GUI, který jste vybrali. Pod ním existuje řada funkcí,
které parsují .config, Kconfig, zapisují konfiguraci
jako definice do hlavičkových souborů a mnoho dalších. Nikomu nic nebrání v
tom napsat vlastní rozhraní, které bude volat funkce a bude postavené nad jeho
oblíbeným prostředí (třeba konfigurovat jádro psaním kódu v base64 ;)).
Zmínil jsem soubor Kconfig, není jeden, ale téměř v každém
adresáři jako Makefile. V něm jsou texty, odpovídající každému
ovladači, které si je možné přečíst po stisku Help, ?, …,
podle prostředí., které používáte ke konfiguraci. Obsahují také nastavení, jak
se má chovat konfigurátor – jak má řešit závislosti, co dalšího má
vybrat ke kompilaci, když zvolíte nějaký
ovladač (na čem závisí), co vám nedovolí vybrat, když nemáte v jádře něco
jiného (např. síťové zařízení, když nemáte povolenou síť) a pod.
Po uložení je vygenerován jednak soubor, podle kterého se orientuje
make a překládá jen to, co jste zvolili a jednak hlavičkový
soubor, který obsahuje tytéž informace, podle kterých jsou nastaveny podmínky
ve zdrojových kódech (např. pokud máte procfs, je nastavené makro
PROC_FS a kód, který je takovýmto makrem podmíněný se přeloží,
čímž v tomto virtuálním filesystému vytvoří ovladač svůj záznam).
Samozřejmě podle vybrané architektury se vytvoří adresář include2 a v něm jsou
odkazy na hlavičkové soubory závislé na architektuře, aby mohl developer
jednoduše udělat #include <asm/cokoliv.h> a nestarat se o
to, na jaké platformě kompilace probíhá.
To je v podstatě vše, v Makefiles jsou skupiny -m, -y a -n odpovídající
modulu, do jádra, nebo vůbec ne. Potom se čistým jazykem c, resp.
zašpiněným gcc (jiným překladačem jádro nepřeložíte) verze aspoň 3.4,
překládá -m a -y; -m se potom linkuje do samostatného .ko, -y v každém adresáři
do built-in.o, všechny nejnadřazenější built-iny do monolitu spolu se zaváděcí
oblastí. Monolit se může zmenšit kompresí (z Image, nebo big z Image). K
dispozici vám také zůstane vmlinux, což je nekomprimovaná verze,
kterou můžete spolu s /proc/kcore předhodit gdb (a vytisknout si
třeba jiffies: p jiffies).