Mikrokernel

Úvod

Prvé kernely operačného systému boli malé aj kvôli limitovanej pamäti počítačov. Ako schopnosti počítačov rástli, množstvo zariadení, ktoré musel kernel riadiť, rástlo tiež. Prvotné verzie UNIXov mali kernely strednej veľkosti, aj keď obsahovali nastavenia ovládačov a manažérov systémových súborov. Keď sa veľkosti adries zväčšili z 16 na 32 bitov, dizajn kernelu nemusel byť viac preplnený hardwareovou architektúrou a kernely začali narastať (Pozri História Unixu).
Berkeley Unix (BSD)-om začala éra veľkokapacitných kernelov. Navyše k vykonávaniu základného systému skladajúceho sa z CPU, diskov a tlačiarní, BSD začal pridávať prídavne súborové systémy, kompletný TCP/IP sieťový systém a množstvo "virtuálnych" zariadení, ktoré umožnili existujúcim programom pracovať neviditeľne (na pozadí) cez sieť. Tento rast pokračoval niekoľko desaťročí, čo malo za následok vznik kernelov s miliónmi riadkov zdrojového kódu. Následkom tohto rastu kernely boli viac náchylné k chybám a stávali sa stále viac a viac náročné na údržbu.
Mikrokernel bol skonštruovaný tak, aby sa vysporiadal s narastajúcou veľkosťou kernelov a potiažami, ktoré prichádzali s nimi ruka v ruke. Teoreticky, mikrokernelova štruktúra poskytla ľahšiu správu kódu vzhľadom na jeho delenie na služby používateľského priestoru. Toto taktiež počítalo s narastajúcou bezpečnosťou a stabilitou vychádzajúc zo zredukovaného množstva kódu prebiehajúceho v kernel móde.
Napríklad, ak sieťová služba spadla kvôli pretečeniu buffera, iba pamäť sieťovej služby by bola narušená a ostatok systému by zostal neporušený. V tradičnom monolitickom kerneli pretečenie by mohlo narušiť pamäť ostatných ovládačov a možno aj kernel samotný, ktorý by mohol spôsobiť zrútenie celého systému.

Vnútro-procesová komunikácia

Vnútro-procesová komunikácia (IPC) je nejaký mechanizmus, ktorý umožňuje oddeľovanie procesov na to, aby mohli spolu komunikovať obyčajne posielaním správ. (Zdieľaná pamäť je v úzkom slova zmysle tiež medziprocesovým mechanizmom komunikácie, ale skratka IPC sa zvyčajne týka iba prechodu správ, a to je to, čo je obzvlášť relevantné pre mikrokernely.) To dovoľuje operačnému systému, aby bol vystavaný zo skupiny malých programov nazývaných servery, ktoré sú používané ďalšími programami v systéme volanými cez IPC. Väčšina alebo všetky podpory pre periférny hardware je ovládaný takýmto spôsobom, so servermi pre ovládače zariadení, súbory sieťových protokolov, súborové systémy, grafiky, atď.
IPC môže byť synchrónny alebo asynchrónny. Asynchrónny IPC je analogický so sieťovou komunikáciou: odosielateľ zasiela správu a pokračuje vo vykonávaní. Príjmateľ overuje dostupnosť správy pokúšaním sa o jej prijatie, alebo je na to upozornený prostredníctvom oznamovacieho mechanizmu. Asynchrónne IPC vyžaduje od kernelu, aby udržoval buffery a fronty na správy, a zaoberá sa pretečeniami bufferu; to tiež vyžaduje dvojité kopírovanie správ (odosielateľ kernelu a kernel príjmateľovi). V synchrónnom IPC, prvá strana (odosielateľ príjmateľovi) blokuje pokiaľ druhá strana nie je pripravená vykonať IPC. Nevyžaduje to ukladanie do zásobníka ani viaceré kópie, ale bez akýchkoľvek pochýb, takéto konflikty môžu robiť programovanie zložitým. Väčšina programátorov preferuje asynchrónne posielanie a synchrónne príjmanie.
Prvá generácia mikrokernelov podporovala synchrónne aj asynchrónne IPC a pripúšťala nízku výkonnosť IPC. Jochel Liedtke označil dizajn a implementáciu IPC mechanizmov ako základný dôvod tejto slabej výkonnosti. V jeho L4 mikrokerneli zaviedol nové techniky, ktoré viedli k výnosu z veľkosti redukcii v IPC výdavkoch. Tieto zahŕňajú IPC systémové volanie, ktoré podporuje posielanie rovnako ako získavanie operácií, robenie všetkých IPC synchrónne a umožňujú, aby registrami prechádzalo čím viac dát. Navyše, Liedtke predstavil koncept "priameho prepnutia procesu", keď počas vykonávania IPC sa spraví (neúplné) prepnutie kontextu priamo od odosielateľa k príjmateľovi. Ak, ako v L4, časť alebo všetky správy prešli registrami, tieto premiestnenia sa v registerovej časti správy nachádzajú bez akýchkoľvek kópií. Okrem toho, vrchné volanie plánovača sa obíde; to je zvlášť prospešné vo všeobecnom prípade kde IPC je používané v RPC tvare volaním servera klientom. Ďalšia optimalizácia, volaná "lenivé plánovanie", sa vyhýba kríženiu plánovania radov počas IPC, tým že necháva vlákna blokované počas IPC v pripravenom rade. Keď je raz plánovač vyvolaný, premiestňuje také vlákna do vhodného čakajúceho radu. Ako v mnohých prípadoch vlákno sa stane odblokovaným pred ďalším vyvolaním plánovača, to spôsobí uloženie dôležitej práce. Podobné prístupy boli odvtedy prijaté QNX a Minix 3.
V klient-server systéme, väčšina komunikácie je v podstate synchrónna, aj keď používa asynchrónne primitívy, ako typická operácia je volanie servera klientom a potom čakanie na odpoveď. To si tiež pre seba požičiava výkonnejšie implementácie, moderné mikrokernely spravidla nasledujú vedenie L4 a poskytujú iba synchrónne IPC primitíva. Asynchrónne IPC môže byť implementované na vrchu použitím pomocníka vlákien. Ale, verzia L4 rozmiestnená v komerčných produktoch ukázala aké nevyhnutné je pridať asynchrónny oznamovací mechanizmus pre lepšiu podporu asynchrónnej komunikácie. Tento mechanizmus podobný signálu neobsahuje dáta a preto nevyžaduje vyrovnávaciu pamäť v kerneli.
Keďže synchrónne IPC blokuje prvú stranu pokiaľ ďalšia nie je pripravená, neobmedzené použitie môže ľahko viesť k uviaznutiu. Navyše, klient môže ľahko inštalovať útok popretie služby na serveri poslaním žiadosti a pritom sa nikdy nepokúsiť získať odpoveď. Takže synchrónne IPC musí poskytnúť prostriedky na prevenciu nekonečného blokovania. Veľa mikrokernelov poskytuje timeouty na IPC volania. ktoré limitujú čas blokovania. V praxi, citlivo vybrať hodnoty timeout je ťažké a systémy takmer nevyhnutne použijú nekonečné timeouty pre klienty a nulové timeouty pre servery. Ako dôsledky, trendom je neposkytovanie ľubovoľných timeoutov, ale iba znamenie, ktoré naznačuje, že IPC by mohlo ihneď zlyhať ak partner nie je pripravený. Tento prístup efektívne poskytuje výber dvoch timeout hodnôt nula a nekonečno. Posledné verzie L4 a Minix sa uberali touto cestou (staršie verzie L4 používali timeouty ako ich používa QNX).

Servery

Mikrokernel servery sú v podstate daemon programy ako ostatné, okrem toho kernel podporuje niektoré z ich privilégií na interakciu s časťami fyzickej pamäte, ktoré sú ináč mimo dosahu pre väčšinu programov. Toto umožňuje niektorým serverom, hlavne ovládačom zariadení, interakciu priamo s hardwarom.
Základná séria serverov so zameraním na mikrokernel zahŕňajú servery súborového systému, servery ovládačov zariadení, servery sietí, servery zobrazenia a servery rozhrania používateľského zariadenia. Táto séria serverov (získané z QNX) poskytuje zhruba sériu služieb ponúkaných monolitickým UNIX kernelom. Nevyhnutné servery sa štartujú pri štartovaní systému a ponúkajú slúžby, také ako súbor, sieť a prístup zariadenia až po obyčajnné programové aplikácie. S takými servermi bežiacimi v prostredí používateľskej aplikácie, vývoj serverov je podobný vývoju obyčajnej aplikácie, skôr než postaviť a zaviesť proces, ktorý je potrebný pre vývoj kernelu.
Dodatočne, veľa "padnutí" môže byť opravených jednoduchým zastavením a reštartovaním servera. (V obyčajnom systéme, padnutie v hociktorom kernel rezidentnom kóde by malo za následok padnutie celého stroja, vynútený reboot.) Ale, časť systémového stavu sa stratí s chybovým serverom, preto tento prístup vyžaduje aplikácie na vyrovnanie sa so zlyhaním. Dobrým príkladom je server zodpovedný za TCP/IP spojenie: Ak je tento server reštartovaný, aplikácie zažijú "stratenie" spojenia, normálny jav v sieťovom systéme. Pre ostatné služby, zlyhanie je menej očakávané a môže vyžadovať zmeny v kóde aplikácie. Pre QNX, schopnosť reštartu je ponúkaná ako QNX Vysoko Dostupný Toolkit (pomocné programové vybavenie).
Kvôli snahe spraviť všetky servery reštartovateľné, niektoré mikrokernely sa koncentrovali na pridávanie rôznych databázam podobných techník ako transakcie, repliky a checkpointing (auto-zápis kontrolných bodov) kvôli zachovaniu dôležitých stavov po reštartovaní jedného serveru. Príkladom je ChorusOS, ktorý bol ohrozovaný aplikáciami vysokej kvality v telekomunikačnom svete. ChorusOS obsahoval funkcie, ktoré umožňovali každému "správne napísanému" serveru to, aby bol kedykoľvek reštartovaný s tým, že klienty, ktoré využívali tieto servery by boli pozastavení do doby, kým by sa server znovu nedostal do pôvodného stavu. Ale, také rysy kernelu sú nekompatibilné s princípom minimality a preto nie sú poskytované v moderných mikrokerneloch, namiesto spoliehania sa na vhodné protokoly užívateľskej úrovne.

Ovládače zariadenia

Ovládače zariadenia často uskutočňujú priamy prístup do pamäte(DMA), takže môžu písať na ľubovoľné miesta fyzickej pamäte, vrátane štruktúry nad dátami kernelu. Také ovládače preto musia byť dôveryhodné. Je všeobecne mylnou predstavou, že to znamená, že musia byť časťou kernelu. V skutočnosti, ovládač nie je sám o sebe veľmi dôveryhodný tým, že je časťou kernelu.
Pokiaľ beží ovládač zariadenia v používateľskom móde nie nevyhnutne zmenšuje poškodenie, ktoré zle správajúci sa ovládač môže spôsobiť, v praxi je to priaznivé pre stabilitu systému v prítomnosti buggy (skôr zákerných) ovládačov: narušenia v prístupe do pamäte samým kódom ovládača (ako protikladné zariadenie) môže byť stále chytené správou pamäťového hardwaru. Navyše, veľa zariadení nie je schopné DMA, ich ovládače môžu byť nedôveryhodné tým, že ich spustíme v používateľskom móde. Nedávno, zvyšujúci sa počet počítačových rysov IOMMUy, veľa z nich môže byť použitých na obmedzenie prístupu zariadenia do fyzickej pamäte. (IBM sálový počítač mal IO MMU a odvtedy IBM System/360 Model 67 a System/370.) To tiež dovoľuje ovládačom používateľského módu stať sa nedôveryhodnými.
Ovládače používateľského módu sa v skutočnosti začali vyskytovať skôr než mikrokernely. Michiganský Terminálový Systém (MTS), v 1967, podporoval ovládače užívateľského priestoru, prvý operačný systém skonštruovaný s takouto schopnosťou. Historicky, ovládače boli menším problémom, zatiaľ čo počeť zariadení bol malý a rozhodne dôveryhodný, takže mať ich v kerneli v zjednodušenom tvare a vyhýbať sa potenciálnemu vykonaniu problémov. To viedlo k tradičnému štýlu kernelovského ovládača v UNIX, Linux a Windows. S bujnením rôznych druhov periférií, množstvo kódu ovládača sa vystupňoval a v modernom operačnom systéme dominuje kernel z hľadiska veľkosti kódu.

Vykonávanie

Získavanie služieb je samo o sebe drahšie v systéme založenom na mikrokerneli ako v monolitickom systéme. V monolitickom systéme, služby získané pomocou jedného systémového volania, ktoré požaduje dva prepínače módu (zmeny v procesoroch privilegovaného levelu). V systéme založenom na mikrokerneli, služby sú získavané posielaním IPC správy serveru a získavanie výsledkov v ďalšej IPC správe od serveru. Toto vyžaduje kontextový prepínač ak sú ovládače implementované ako procesy, alebo volanie funkcie, ak sú implementované ako procedúry. Navyše, podávanie aktuálnych dát serveru a späť môže mať za následok podstatné zväčšovanie mimoriadnych výdavkov, zatiaľ čo v monolitickom systéme kernel môže priamo pristupovať k dátam v klientských bufferoch.
Vykonanie je preto potenciálnym sporom v systémoch mikrokernelu. V skutočnosti, skúsenosti prvej generácie mikrokernelov takých ako Mach a Chorus ukázali, že systémy založené na nich podávali úbohé výkony. Ale Jochen Liedtke ukázal, že výkonové problémy Machu boli výsledkom úbohého dizajnu a implementácie, a špeciálne Machova neúmerná cache stopa. Liedtke demonštroval s jeho vlastným L4 mikrokernelom, že prostredníctvom opatrného dizajnu a implementácie, a špeciálne nasledovaním princípu minimality, IPC cena môže byť redukovaná viac než výnos veľkosti v porovnaní s Mach. IPC výkon L4 je stále neporaziteľný naprieč hranicami architektúr.
Pokiaľ tieto výsledky demonštrovali, že úbohý výkon systémov založených na prvej generácii mikrokernelov nie je zástupcom druhej generácie kernelov tak ako L4, to neznamená žiadny dôkaz, že systémy založené na mikrokerneloch môžu mať dobrý výkon. Bolo ukázané, že monolitický Linuxový server spojený s L4 vyžaduje iba zopár percent mimoriadnych výdavkov oproti čistému Linuxu. Ale, taký jednoserverový systém ukazuje iba zopár, ak vôbec nejaké výhody, výhody mikrokernelov sú údajne poskytnuté štruktúrovaním funkcionality operačného systému do oddelených serverov.
Existuje zopár komerčných multiserverových systémov, v jednotlivých realtime systémoch QNX a Integrita(operačný systém). Nekomplexné porovnanie vzájomného výkonu s monolitickými systémami bolo publikované pre multiserverové systémy. Okrem toho, vykonanie sa nezdá byť prvoradým záujmom pre tie komerčné systémy, ktoré namiesto toho aby vyzdvyhovali jednoduchosť voči robustnosti. Pokus o postavenie vysoko výkonného multiserverového operačného systému bol IBM Sawmill Linux projekt. Ale tento projekt nebol nikdy dokončený.
Medzitým bolo ukázané, že ovládacie zariadenia používateľského levelu sa môžu priblížiť výkonom ovládačom kernelu dokonca aj pre vysoko priepustné, vysoko prerušované zariadenia ako Gigabit Ethernet. Zdá sa, že to znamená nemožnosť existencie vysoko výkonných multiserverových systémov.

Bezpečnosť

O bezpečnostných výhodách mikrokernelu sa často debatovalo. V súvislosti s bezpečnosťou, princíp minimality mikrokernelov je priamy dôsledok princípu najmenších privilégií, podľa ktorého by všetky kódy mali mať iba privilégiá potrebné na poskytnutie nutnej funkcionality. Minimality vyžadujú, aby systémová dôveryhodná výpočtová báza(TCB) bola udržiavaná minimálna. Keďže kernel (kód, ktorý sa vykonáva v privilegovanom móde hardwaru) je vždy časťou TCB, jeho minimalizovanie je prirodzene v dizajne bezpečnostného ovládača.
Takže, dizajn mikrokernelu bol použitý pre systémy navrhnuté ako aplikácie vysokej bezpečnosti, vrátane KeyKOS, EROS a vojenských systémov. V skutočnosti common criteria (CC) v najvyššom bezpečnostnom leveli (EAL7) mali jasné požiadavky, aby cieľ ohodnotenia bol “jednoduchý”, čiže uznanie praktickej nemožnosti vytvorenia pravej dôveryhodnosti pre systém ako celok.
Nedávna práca na mikrokerneloch je zameraná na formálnych špecifikáciách kernel API, a formálne dôkazy bezpečnosti vlastností API. Prvým príkladom tohto matematického dôkazu sú obmedzenia mechanizmu v EROS, založené na zjednodušenom modeli EROS API. Nedávno, pomocou uplného súboru dôkazov kontroly stoja(machine-checked) boli predvedené vlastnosti ochranného modelu seL4 verzie L4.
Niektoré projekty idú ešte ďalej, sú namierené na celkové formálne overenie, t. j. matematický dôkaz, že implementácia kernelu je zhodná s jeho špecifikáciou, čo potom poskytuje garanciu, že vlastnosti overené o API skutočne platia pre ozajstný kernel. Tento stupeň dôvery ide dokonca za CC EAL7. O také dôkazy sa pokúšali pre Coyotos a seL4. Doplňam, že sa takovéto dôkazy podarilo realizovať pro mikrokernel Fiasco a najmä pre seL4 viď článok na české Wikipédii.