Ovladače zařízení
Úplně na začátku je bezesporu vhodné si samotný pojem ovladače zařízení (device drivers) nejprve srozumitelně definovat.
Ovladače zařízeníPojmy ovladač zařízení a ovladač budou v textu libovolně zaměňovány. jsou speciální programy, které uživatelským programům běžícím v operačním systému, zpřístupňují funkcionalitu zařízení, např. myši, tiskárny apod. Uživatelské programy díky tomu na zařízení nepřistupují přímo, ale prostřednictvím systémových volání, které operační systém přesměruje na volání funkcí ovladače. Ve většině případů dokonce programy nepoužívají přímo ani systémová volání, ale s výhodou volají funkce knihovny libc, která řeší veškeré složitosti spojené s používáním systémových volání.
Účelem ovladačů je odstínit ostatní programy od složitostí spojených s řízením zařízení. Ovladače proto definují jedno nebo více rozhraní, přes které mohou se zařízením komunikovat uživatelské aplikace (prostřednictvím systémových volání) a případně i jiné části operačního systému (další ovladače). Rozhraní ovladačů se definují tak, aby byla co nejobecnější a nejjednodušší a aby se zařízení stejného typu ovládala stejně. Samotnou problematiku řízení konkrétního typu zařízení pak řeší pouze kód ovladače.
Tento přístup ve výsledku zjednodušuje návrh uživatelských aplikací. Tak například v textovém editoru lze tisknout na libovolnou tiskárnu, i když autor editoru nemá ani potuchy o tom, jak se daná tiskárna ovládá. Stačí, když textový editor bude při tisku volat obecné tiskové rozhraní operačního systému, kde editor běží. Ovladač připojené tiskárny pak už sám zajistí co nejoptimálnější tisk, aby byl tiskový výstup co nejlepší.
V případě operačního systému Linux, který je tvořen jádrem (ano celý Linux je jen jádro operačního systému, vše okolo je součástí distribuce), ovladače rozšiřují funkcionalitu jádra o schopnost ovládat podporované zařízení.
Typy ovladačů
Základní dělení ovladačů je podle typu zařízení, které ovladač obsluhuje. Zařízení rozdělujeme na:
- znaková zařízení (char devices), které se chovají jako řetězec dat, ke kterému lze přistupovat výhradně sekvenčně, tj. podobně jako k obsahu souboru, s tím rozdílem, že ne všechny znakové ovladače umožňují návrat či posun vpřed v řetězci dat.
- bloková zařízení (block devices), která umožňují blokový přístup, tj. přenést jeden nebo více bloků dat z/do zařízení z/na náhodnou pozici.Poznámka: Souborové systémy lze provozovat pouze na blokových zařízeních.
- síťová zařízení (network devices), která slouží pro komunikaci s jinými počítači. Na rozdíl od znakových a blokových zařízení nepracují s řetězcem či blokem dat, ale s pakety.
Mluvíme potom o ovladačích znakových (char device drivers), blokových (block device drivers) a síťových zařízení (network device drivers).
S ohledem na jednoduchost implementace se budeme v dalším textu zabývat pouze vývojem ovladačů pro znaková zařízení.
Rozdělení zařízení a návazně i ovladačů podle typu přístupu je nepřesné, protože Linux umožňuje k blokovým zařízením přistupovat i znakově. Zařízení znaková je proto běžnější vnímat jako zařízení, která nemají vyrovnávací paměť, zatímco bloková zařízení jako ta, která ji mají.
Prostor jádra
Než si ukážeme, kde ”žijí” ovladače, musíme si objasnit dva zásadní pojmy - prostor jádra a uživatelský prostor. Tyto pojmy úzce souvisí s tím, jak programy v operačním systému přistupují k paměti a s jakou úrovní oprávnění mohou tyto programy běžet. Proto si o těchto mechanismech něco řekneme.
V operačním systému Linux nemohou programy k operační paměti přistupovat přímo, ale prostřednictvím mechanismu virtualizace paměti. Operační systém Linux nad operační pamětíAle nejen nad ní. Do adresového prostoru procesoru se totiž mapují všechny periferie jako pevný disk apod., resp. nad adresovým prostorem procesoru vytváří tzv. virtuální adresové prostory. Ty můžeme chápat jako nezávislé virtuální paměti. Každému uživatelskému programu Linux přidělí vyhrazený virtuální adresový prostor (virtuální paměť), který je od adresových prostorů ostatních programů oddělen a izolován. Podobně i jádro systému běží ve svém vyhrazeném adresovém prostoru.
Tento mechanismus dává operačnímu systému plnou kontrolu nad přístupem k operační paměti a k periferiím namapovaným do skutečného adresního prostoru procesoru. Oddělením adresových prostorů uživatelských programů a jádra se značně zvyšuje stabilita a bezpečnost operačního systému - pokud se nějaký program pokusí přistoupit k paměti, ke které nemá povolený přístup, tak jej operační systém ihned ukončí (známé ”segmentation fault”). Zároveň žádný uživatelský program nemůže přistoupit na paměť vyhrazenou jádru operačního systému.
Kromě virtualizace adresového prostoru nabízejí moderní procesory i možnost určit v jakém módu procesor, resp jeho centrální jednotka CPU, poběží. Módy CPUNebo také úroveň oprávnění (CPU privilege levels) (CPU modes) definují množinu operací, které běžící programy mohou vykonávat. Většinou dnešních procesorů jsou podporovány minimálně dva režimy - režim neomezeného přístupu (unrestricted mode, také supervisor mode) a režim omezeného přístupu (restricted mode či user mode). V režimu omezeného přístupu nelze přistupovat do některých částí paměťového prostoru a nelze vykonávat instrukce, které mění celkový stav systému (např. změna módu CPU). Naopak v režimu neomezeného přístupu lze vykonávat kód běžícího programu bez omezení.
Módy CPU jsou využívány operačním systémem, kdy jádro systému běží vždy v módu neomezeného přístupu, zatímco ostatní méně kritické části operačního systému a stejně tak i všechny uživatelské programy běží v módu omezeného přístupu.
Z pohledu přidělování paměti a z pohledu módů CPU operační systém Linux rozděluje prostor v kterém programy běží na dvě části:
- prostor jádra (kernel space) - je to vyhrazený adresový prostor, který je k dispozici pouze jádru. Veškerý kód v tomto prostoru běží v módu neomezeného přístupu.
- uživatelský prostor (user space) - v tomto prostoru má každý program vyhrazen svůj adresový prostor. Všechny programy v tomto prostoru běží v módu omezeného přístupu.
Přechod mezi těmito prostory se nazývá přepnutí kontextu (context switching). Dochází k němu vždy, když uživatelský program zavolá nějakou službu jádra prostřednictvím systémového volání. Systémové volání zajistí přepnutí kontextu a vykonání požadované funkcionality v prostoru jádra. Po obsloužení požadavku v prostoru jádra vrátí systémové volání řízení zpět do uživatelského prostoru, případnou chybu uloží do proměnné errno a vrátí odpovídající návratovou hodnotu do uživatelské aplikace. Ta pak pokračuje dál ve svém běhu.
Rozhraní ovladačů
Konečně se dostáváme k tomu, kde v systému Linux ”žijí” ovladače zařízení. Jak asi už tušíte, ovladače jsou součástí jádra, tedy i prostoru jádra (kernel space).
Obrázek 1.1 zachycuje ”životní prostor” ovladače. Směrem k uživatelskému prostoru je funkcionalita ovladače přístupná pomocí standardní sady systémových volání (rozhraní A), které jsou namapovány na funkce ovladače. Tato systémová volání jsou většinou ještě skryta za funkcemi knihovny libc, aby uživatelská aplikace nemusela řešit řadu detailů spjatých s voláním funkcí systému. Sadu systémových volání nazýváme standardní proto, že ovladače znakových a blokových zařízení jsou v Linuxu uživatelským aplikacím prezentovány jako soubory. Z toho důvodu se k přístupu k ovladačům používá stejná sada systémových volání jako při přístupu k souborům. Linux totiž dodržuje konvenci ze světa unixových systémů, že vše je soubor.
K samotnému zařízení (HW) ovladač nepřistupuje přímo, ale pomocí sady funkcí pro čtení a zápis z/do I/O portů a I/O pamětí, které poskytuje jádro (rozhraní B).
Jednotlivé funkce obou rozhraní A a B si postupně představíme později.