My photo
›› [updates]

Linux Kernel

Obsah


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

Jak lze v
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
Jste-li zastánci klikacích nástrojů, zvolíte
make xconfig nebo make gconfig
které jsou postavené na gtk a qt designu.

Jak 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 mrproper

což 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
nebo
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 rmmod pro 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…
  • 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í

Aneb jak to všechno udělat ve zkratce a neztratit body.
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
Jak jednoduché…

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].


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).

.
Copyleft (c) 2008-2010 Jiri Slaby