# Architektury jádra: monolit, mikrojádro a co z toho vyhrálo

V lednu 1992 poslal Andrew Tanenbaum do diskusní skupiny comp.os.minix příspěvek s nadpisem „LINUX is obsolete". Autor MINIXu v něm vysvětlil, že monolitické jádro je návrat do sedmdesátých let a že mikrojádra ten spor už vyhrála. Torvalds odpověděl a debata se táhla týdny.

Po třiceti letech je vidět, že pravdu měl každý z nich, jen jinde. Monolit vyhrál na serverech, desktopech a v telefonech. Mikrojádro vyhrálo tam, kde pád ovladače stojí životy: v autech, v letecké technice a - což je pěkná ironie - uvnitř každého moderního procesoru Intel běží MINIX.

Tahle stránka vysvětluje, čím se ty architektury liší a proč se ten rozdíl nedá zredukovat na „rychlost proti spolehlivosti". Neřeší samotnou hranici mezi režimy - to je na [jádru a uživatelském režimu](Jadro-a-uzivatelsky-rezim) - ani jeden přechod přes ni, což je [systémové volání](Systemova-volani). Bez těch dvou stránek zůstane zbytek jen názvoslovím.

## Hranice ochrany, ne architektura

Uvnitř jádra sdílí veškerý kód jeden adresní prostor, běží v privilegovaném režimu a smí sáhnout na cokoli. Venku má vlastní adresní prostor a každý kontakt s okolím musí projít přes jádro.

Tohle je nejdůležitější věc na celé stránce: **otázka nezní „monolit, nebo mikrojádro", ale co je uvnitř hranice ochrany.** Každý kus kódu uvnitř může položit celý stroj. Každý kus kódu venku platí za každý přechod hranice.

Celý ten třicetiletý spor je o tuhle jednu směnu.

## Monolitické jádro: co všechno je uvnitř

V Linuxu je uvnitř [plánovač](Planovani-procesu), [správa paměti](Sprava-pameti) i s tabulkami stránek, [souborové systémy](Souborovy-system), síťový zásobník, obsluha [přerušení](Preruseni-a-vyjimky) a ovladače všeho, co se dá k počítači připojit. Zdrojový strom má přes třicet milionů řádků a největší část zabírají právě ovladače.

**Uvnitř je volání obyčejný skok.** Když síťový zásobník potřebuje paměť, zavolá funkci: jednotky nanosekund, žádné přepnutí, žádné kopírování. Odtud plyne výkon monolitu.

**Cena je, že chyba nemá kam spadnout.** Ovladač, který zapíše mimo své pole, přepíše datovou strukturu plánovače. Nulový ukazatel v ovladači není výjimka procesu, ale [panika jádra](Start-systemu).

### Moduly nejsou mikrojádro

Nejčastější omyl kolem architektur zní: Linux má moduly, takže je vlastně mikrojádro. **Není.**

```bash
lsmod                   # zavedené moduly a kolik věcí každý z nich používá
modinfo xfs             # závislosti, parametry, licence a podpis modulu
sudo modprobe -r xfs    # vysunutí; selže, dokud je svazek připojený
```

Modul se zavádí a odebírá za běhu, ale jakmile je uvnitř, běží ve **stejném adresním prostoru se stejnými právy** jako zbytek jádra. Vidí všechny symboly, může měnit cokoli, a když spadne, položí stroj stejně jako kód přeložený napevno.

**Modul je otázka zavádění, ne ochrany.** Distribuce ho používá proto, aby jedno jádro nabootovalo na tisících různých strojů. S izolací nemá nic společného.

Rada „přelož si ovladače napevno kvůli výkonu" je zbytek doby, kdy zavádění modulů něco stálo. Po zavedení je to tentýž kód se stejnými právy.

## Mikrojádro: co zůstane, když zbytek vystrčíš ven

V jádře zůstane jen to, co bez privilegovaného režimu nejde: plánování, správa adresních prostorů a předávání zpráv. Zbytek - ovladače, souborové systémy, síť - jsou běžné procesy s vlastní pamětí.

Ovladač disku, který sáhne mimo, dostane od jádra chybu, umře jako kterýkoli jiný proces a dozorčí proces ho restartuje. Systém běží dál.

**Cena je IPC.** Operace, která byla v monolitu skokem, je teď [meziprocesová komunikace](Meziprocesova-komunikace): přechod do jádra, předání zprávy, [přepnutí kontextu](Prepinani-kontextu) na obslužný proces a totéž zpátky. Jedno čtení ze souboru překročí hranici čtyřikrát místo jednou a jeden přechod stojí zhruba 50-100 ns, s mitigacemi Spectre a Meltdown i pětinásobek.

Ten argument byl v roce 1992 silnější než dnes: L4 z roku 1993 srazilo cenu zprávy o řád a ukázalo, že pomalý byl Mach, ne myšlenka.

### Kde mikrojádro doopravdy vyhrálo

**QNX** - infotainment a přístrojové štíty v autech, průmyslové řízení, zdravotnická technika. Certifikace podle norem funkční bezpečnosti se na malé důvěryhodné bázi dělá řádově snáz.

**seL4** - mikrojádro o zhruba deseti tisících řádcích C se strojově ověřeným důkazem, že implementace odpovídá své specifikaci. Není to důkaz, že postavený systém je bezpečný - jen že jádro dělá právě to, co je ve specifikaci.

**MINIX 3** - od generace Skylake (2015) běží varianta MINIXu 3 uvnitř Intel Management Engine, tedy na samostatném procesoru v čipsetu prakticky každého moderního Intelu. O tom jádru přitom skoro nikdo neví a nikdo nad ním nemá kontrolu.

## Hybridy: Windows NT a XNU

Windows NT navrhl Dave Cutler jako vrstvený systém s mikrojádrovými rysy: podsystémy prostředí v uživatelském režimu a jasně vymezené vrstvy uvnitř. XNU v macOS je doslova složenina - jádro odvozené z Machu pro správu paměti a zprávy, nad ním BSD vrstva pro procesy, souborové systémy a sokety.

**Obojí si vzalo z mikrojádra strukturu a z monolitu adresní prostor.** Komponenty jsou oddělené rozhraními, ale běží vedle sebe se stejnými právy. BSD vrstva v XNU s Machem nemluví zprávami, volá funkce.

### Proč grafika skončila v jádře i tam

NT 4.0 v roce 1996 přesunul grafický podsystém a správce oken z uživatelského procesu dovnitř jádra, do `win32k.sys`. Důvod byl jediný: každé vykreslení znamenalo přechody hranice a na tehdejším hardwaru to bylo vidět. Windows tím získalo rychlost a jednu z nejplodnějších oblastí zranitelností ve své historii - chyba v kreslení fontu je najednou chyba v ringu 0.

macOS jde dnes opačným směrem a od verze 10.15 (2019) tlačí ovladače ven přes DriverKit. **Kdykoli se ale výkon a izolace potkají na horké cestě, vyhraje výkon.**

## Tři architektury vedle sebe

| Vlastnost | Monolit | Mikrojádro | Hybrid |
|---|---|---|---|
| Volání mezi částmi | skok, jednotky ns | zpráva, stovky ns až µs | podle vrstvy |
| Pád ovladače | položí stroj | restart služby, běží dál | většinou položí stroj |
| Důvěryhodná báze | miliony řádků | tisíce až desítky tisíc | miliony řádků |
| Ladění | výpis z paniky | debugger na proces | výpis z paniky |
| Kde běží | **Linux, BSD, Android** | **QNX, seL4, Intel ME** | **Windows NT, macOS** |

Z toho plyne, co se v praxi děje: **rozhoduje se podle toho, co stojí selhání, ne podle toho, co stojí volání.** Na serveru je pád stroje nepříjemnost, v řídicí jednotce brzd jiná kategorie problému.

## Exokernel a unikernel: jedna aplikace, jedno jádro

Exokernel z devadesátých let posunul myšlenku opačným směrem: jádro jen bezpečně rozděluje hardware a veškerou abstrakci si aplikace linkuje jako knihovnu. Unikernel je jeho praktický potomek - aplikace a knihovní systém se přeloží do jednoho obrazu, který běží v jediném adresním prostoru přímo nad hypervizorem.

Obraz má jednotky megabajtů, startuje v desítkách milisekund a systémová volání nestojí nic, protože žádná hranice není.

**Pro tvůj server to není.** Nemáš shell, nemáš `ps`, nemáš druhý proces, kterým bys to opravil, a chyba v aplikaci má rovnou přístup ke všemu. Smysl to dává na specializované virtuální stroje s tisíci jednoúčelových instancí. Všechno ostatní se dělá [kontejnery](Virtualizace-a-kontejnery).

## Kam se to posunulo v praxi

Linux je monolit a zůstane jím. Přesto z něj systematicky tlačí věci ven.

**FUSE** - souborový systém jako obyčejný proces, v jádře od roku 2005. Tak fungují sshfs i ntfs-3g. Cena je několik přechodů hranice na operaci, výhoda je, že chyba v cizím formátu neshodí stroj. Detaily jsou u [VFS a montování](VFS-a-montovani).

**Ovladače v uživatelském prostoru** - SPDK a DPDK obcházejí jádro úplně. Rozhraní `vfio` s pomocí IOMMU předá zařízení procesu, ten si ho ovládá sám a data putují bez jediného systémového volání. Vyplatí se to při milionech paketů za vteřinu, kdy je cena přechodů hlavní položkou rozpočtu. Víc u [vstupu a výstupu](Vstup-a-vystup).

### eBPF: cizí kód v jádře, který smí projít jen ověřovatelem

eBPF je nejzajímavější odpověď na celý ten spor. Nahraješ do jádra vlastní program, ale ověřovatel před spuštěním dokáže, že skončí, že nesahá mimo povolenou paměť a že volá jen povolené funkce.

```bash
sudo bpftool prog show    # jaké programy právě běží v jádře a odkud se tam vzaly
```

Ochranu tady nedělá hranice adresního prostoru, ale **statická kontrola před spuštěním**. Potkáš to v [nástrojích a diagnostice](Nastroje-a-diagnostika), aniž bys tušil, že řešíš architekturu jádra.

**Je to konvergence, ne kapitulace.** Monolit si bere z mikrojádra izolaci tam, kde se vyplatí, a mikrojádrové systémy si berou z monolitu rychlé cesty. Ani jedna strana necouvla, obě jen přestaly platit plnou cenu.

## Jeden ovladač, 8,5 milionu strojů

19. července 2024 vydal CrowdStrike aktualizaci datového souboru pro svůj bezpečnostní senzor. Ten soubor nebyl program, ale zpracovával ho ovladač běžící v jádře Windows a ten na něm spadl. Následovala modrá obrazovka při každém startu, zhruba 8,5 milionu strojů, zrušené lety a stojící nemocnice.

**Poučení je přesně to, o čem je celá tahle stránka: kód uvnitř hranice nemá kam spadnout.** Kdyby tatáž chyba potkala proces v uživatelském prostoru, restartoval by se. Podrobnosti patří na [jádro a uživatelský režim](Jadro-a-uzivatelsky-rezim).

## Kde ta volba přestává být tvoje

Architekturu jádra si nevybíráš. Vybírá ji hardware a to, kde existuje ovladač.

**Ovladač napíšeš tam, kde ho podporuje výrobce čipu, a to je v praxi jádro.** Dokumentace, vzorový kód i rozhraní míří dovnitř. Uživatelský prostor je varianta jen u úzké skupiny zařízení.

**Na serveru volba neexistuje.** Provozuješ Linux nebo Windows, oba jsou monolit s moduly. Ovlivníš jediné: kolik cizího kódu do jádra pustíš.

**Vybírat si smíš u vestavěných zařízení.** Řídicí jednotka v autě, zdravotnický přístroj, průmyslový kontrolér - tam se QNX nebo seL4 vyplatí, protože se počítá cena selhání, ne cena volání.

## Co si odnést

**Rozhoduje hranice ochrany, ne jméno architektury.** Uvnitř je všechno rychlé a smrtelné, venku pomalejší a restartovatelné.

**Modul není mikrojádro.** `lsmod` ukazuje kód se stejnými právy jako zbytek jádra, jen zavedený za běhu.

**Monolit vyhrál tam, kde se počítá propustnost, mikrojádro tam, kde se počítá selhání.** Dvě správné odpovědi na dvě různé otázky.

**IPC je celá cena mikrojádra** a od L4 je řádově nižší, než jak se ten argument pořád opakuje.

**Hybridy jsou monolity se strukturou.** Oddělené komponenty, jeden adresní prostor, jedna panika.

**Linux tlačí věci ven a monolitem být nepřestává.** FUSE, `vfio`, eBPF - konvergence, ne kapitulace.

## Kam dál

- **[Jádro a uživatelský režim](Jadro-a-uzivatelsky-rezim)** - ta hranice, o kterou tu celou dobu jde
- **[Systémová volání](Systemova-volani)** - jak přechod přes hranici vypadá zevnitř
- **[Meziprocesová komunikace](Meziprocesova-komunikace)** - mechanismy, na kterých mikrojádro stojí
- **[Vstup a výstup](Vstup-a-vystup)** - kde ovladače v obou světech doopravdy sedí
- **[Virtualizace a kontejnery](Virtualizace-a-kontejnery)** - druhý způsob, jak izolovat
- **[Start systému](Start-systemu)** - co znamená panika jádra při startu
