Divide By Zero aneb Chybové hlášky Windows

O stabilitě operačního systému Windows bylo napsáno mnoho řádek, většinou nabitých emocemi k prasknutí. Pravda je taková, že dnešní operační systémy jsou natolik komplikované a musí spolupracovat s tak širokou škálou hardware, že by bylo zázrakem, kdyby byly za všech okolnosti stabilní. Je tedy dobré se seznámit s tím, jaké druhy chyb můžou nastat a kde hledat jejich příčiny.

Jeden z Murphyho zákonů říká, že v každém programu je alespoň jedna chyba. Počet chyb narůstá s jeho cenou a s počtem slov, kterými jeho tvůrci přesvědčují veřejnost, že jejich programy jsou bezchybné. Dle této definice musí být ve Windows chyb bezpočet. Na jejich sepsání by nestačilo místo na serveru proto se podíváme jen na chyby způsobující nejčastěji pády programů a celého systému. (Pozn. Tyto řádky berte prosím s humorem, za chvíli přijde trochu náročnější povídání a autor se zřejmě snažil článek “odlehčit”. Nebo že by mu někdo konečně řekl, že články bez špetky bulváru dneska už nikdo nečte? ;-))

Bez teorie se bohužel neobejdeme takže s chutí do toho. Ti šťastní čtenáři, kteří znají princip přidělování času procesům a vědí co to jsou úrovně ochrany a jak jsou implementovány v procesorech 80386 a pozdějších můžou tento odstavec směle přeskočit.

Po operačním systému požadujeme aby umožňoval provádět více úloh současně (např. přehrávání hudby + stahování a zobrazování www stránky z internetu + kontrola pravopisu ve Wordu...) i když ve skutečnosti máme (většinou) jen jeden procesor. Jádro operačního systému přiděluje každému běžícímu procesu postupně krátké časové úseky (Time Slices) v závislosti na prioritě daného procesu, na tom zda čeká na vstupně-výstupní operaci a mnoha dalších faktorech. Proces sám má právo vzdát se svého časového úseku pokud nemá nic na práci. Kdysi velmi dávno (v dobách Windows 3.11) musel proces dobrovolně předat řízení operačnímu systému, mohla tedy nastat situace, že neposlušný proces ukradl celý výpočetní výkon pro sebe a nedovolil sobě a dokonce ani operačnímu systému provádět další úlohy. Většinou se procesy poslušně střídaly ale vinou např. chyby programu mohlo dojít k zacyklení a pomohl jen restart počítače. V tomto uspořádání programy společně s operačním systémem spolupracují na vytvoření iluze současného běhu a proto mluvíme o kooperativním multitaskingu.

V dnešních dobách má již operační systém prostředky jak procesu odebrat vládu nad procesorem. Díky tomu nemůže nastat zablokování systému jedním procesem. Takové uspořádáni nazýváme preemptivním multitaskingem. V časech kdy kraloval DOS musely mít všechny programy, které chtěly využívat nějaké dodatečné nebo nadstandardní vybavení počítače mít ovladače k široké škále daného druhu zařízení. Pamětníci si jistě vzpomenou, že textové editory měly celou řadu ovladačů pro tiskárny, CAD programy pro grafické karty a hry zase pro zvukové karty. Když měl uživatel nepodporované zařízení mohl program využívat většinou jen v omezené míře.

Od moderního operačního systému požadujeme aby unifikoval přístup k hardware aby programy mohly na zařízení přistupovat standardním způsobem. Je vhodné dokonce přímý přístup na zařízení zakázat protože je to potencionálně nebezpečné (Program by mohl např. číst z disku pomocí přímého přístupu i soubory, na které nemá právo atd.). Opět tedy narážíme na situaci, kdy určitý program musí být v privilegované pozici vůči ostatním protože pouze skrze jeho služby smí ostatní programy přistupovat k hardware. A opět se jedná o jádro operačního systému (a softwarové ovladače zařízení, které lze do jisté míry považovat za jeho součásti) které se v této pozici nachází. Operační systém musí zaručit, že provedení aplikací chybné instrukce (tedy sekvence bajtů, která procesoru nedává smysl) nebo instrukce s chybnými argumenty (dělení nulou) nezpůsobí pád celého systému ale jen příslušné aplikace. Poslední funkcí operačního systému, o které se tady zmíníme, je zaručení bezpečného paměťového prostoru pro každý proces. Kdyby poškozený (nebo škodolibý) program mohl zapisovat do paměťového prostoru ostatních procesů pravděpodobně by způsobil také jejich poškození. Pokud bychom dovolili čtení paměti cizího procesu vystavujeme se zase nebezpečí, že "špionážní" program přečte citlivé informace z jiného programu. A opět je zde jádro operačního systému, které přiděluje práva procesům na jednotlivá místa v paměti a trestá procesy, které porušují pravidla slušného chování jejich ukončením (že by virtuální verze trestu smrti v počítačovém světě?).

Ukázali jsme si, že jádro OS musí mít oproti ostatním programům jisté výhody. Ty mu musí poskytnout procesor (jakékoliv softwarové řešení by šlo bez potíží obejít). V případě procesorů vycházejících z architektury 8x86 je to realizováno pomocí tzv. úrovní ochrany. Říkáme, že jádro má úroveň ochrany 0 (někdy také 0 Ring) a uživatelské programy v úrovni ochrany 3 (Intel implementoval ve svých procesorech 4 úrovně ochrany ale v praxi se využívají pouze tyto dvě.). Procesy s vyšší úrovni můžou volat služby pouze procesů s nižší nebo stejnou úrovni, procesy s nižší úrovni můžou číst data procesů se stejnou nebo vyšší úrovni. Pokud se stane chyba ve vyšší úrovni zavolá procesor obslužnou rutinu z nižší úrovně. Jistě teď víte jak se může stát, že v takto dokonale zabezpečeném systému, kde jádro hlídá vznik všech možných chyb přesto dochází k pádům. Chybu přímo v jádru operačního systému již nemá kdo zachytit, nikdo nemůže jádru zabránit aby zničilo paměť procesů a konečně nikdo nemůže jádru zabránit aby provedlo chybnou komunikaci s hardware.

Existují dva protichůdné požadavky: z jedné strany se snažíme udržet jádro co nejmenší a tedy aby mohlo být co nejvíce odladěno a z druhé strany chceme aby programy pracovaly co nejrychleji což z důvodu časové režie přepínání a komunikace různých úrovni ochrany nás nutí jádro zvětšovat. Možná si vzpomenete na vášnivé hádky uživatelů Windows, které proběhly po vzniku NT 3.51. Šlo tehdy právě o spornou záležitost vtažení grafického subsystému do jádra. Přineslo to citelné zrychlení ale bezesporu i snížení stability.

Ještě něco málo k tomu, jak předává procesor informaci o chybě jádru. V případě chyby je vyvoláno přerušení, které předá řízení obslužné rutině a v některých případech i dodatečné informace většinou o adrese v paměti místa vzniku chyby. Rozlišujeme obnovitelné chyby (recoverable error, fault)- konzistence tabulek procesu je zachována, po ukončení přerušení může proces pokračovat a kritické chyby (abort, nonrecoverable error), kdy návrat již není možný.

Po této trochu zdlouhavé a nudné porci teorie přistupme přímo k věci- k seznamu chyb které zachytí jádro, jak na ně reaguje. Postupujme v pořadí od nejméně závažných chyb až po ty fatální:

Chyba 0, Divide By Zero (fault)

Dělení nulou nebo výsledek je větši než rozměr argumentu. O této chybě se uživatel většinou nedozví. Aplikace si s nastalou situaci dokáže buď korektně poradit sama nebo bude nadále pracovat s chybnými daty a pravděpodobně brzy zhavaruje na jiné chybě.

Chyba 1, Debug exception (fault)

Chyba 3, Breakpoint (fault)

Zde se vlastně nejedná o chybu ale o nástroj na krokování a ladění programů proto se nás netýká. Chyba 1 vzniká po každé provedené instrukci a obslužná rutina může např. zobrazit stav registru procesoru atd. Chyba 3 vznikne tehdy, pokud procesor narazí na instrukci INT3. Tato instrukce má jen jeden bajt a dá se pomocí ni nahradit libovolná instrukce. Slouží k umisťování zarážek v programu.

Chyba 4, Overflow (fault)

Aritmetické přetečení, platí to stejné jako pro chybu 0.

Chyba 5,  Bounds check (fault)

Se vyvolá pokud instrukce BOUND detekuje překročení mezí např. indexu tabulky. V praxi téměř nepoužívané. Opět platí to stejné jako pro chybu 0.

Chyba 6, Invalid Opcode (abort)

Procesor narazil na chybnou instrukci - neexistující kód instrukce nebo chybná kombinace operandů. Windows zobrazí hlášku "Program provedl neplatnou operaci na adrese xxxx:xxxx a bude ukončen.". Může se jednat o chybu v programu, paměti nebo procesoru (přetaktování, nedostatečné chlazeni).

Chyba 7, Coprocessor not available (fault)

Pokud se v programu vyskytne požadavek na provedení operace s plovoucí desetinou čárkou ale počítač nedisponuje koprocesorem musí jej jádro emulovat nebo oznámit uživateli, že program nemůže pracovat bez koprocesoru. Windows 9x dělají to první, Linux v závislosti na tom, zda je v jádru zakompilovaná emulace koprocesoru.

Chyba 8, Double Fault (abort)

Během zpracování chyby vznikla další. Velice zřídkakdy se vyskytující chyba. Příčiny jako u chyby 6.

Chyba 9, Coprocessor Segment Overrun (fault)
Chyba A , Invalid TSS (fault)
Chyba B , Segment Not Present (fault)
Chyba C , Stack Exception (fault)

Chyby umístění segmentů, příčiny i následky viz chyba 6.

Chyba D, General Protection Fault
Chyba E, Page Fault (fault)

Chyby při adresaci. Téměř vždy se jedná o signál pro operační systém, že paměť požadována procesem není ve fyzické paměti ale např. ve virtuální paměti na disku. Operační systém provede potřebné operace k nápravě (nahrání příslušných paměťových stránek z disku do paměti) a obnoví provádění procesu. Pokud paměť není nalezena ani na disku jedná se o chybu provádění programu. Příčiny a následky viz chyba 6.

Následující chyby jsou již jakousi translací předchozích chyb pokud se stanou v jádře systému nebo pokud je detekována kritická chyba hardware. Končí se vždy pádem systému a přezdívá se jim BSOD (Blue Screen of Death neboli modrá obrazovka smrti). Bohužel uživatele v takové situaci nejčastěji nervózně resetují počítač bez poznamenáni si řady užitečných, které mnohdy přispěji k vyřešení problému nebo alespoň k vyjasnění příčin. Je tam výpis běžících procesů a dole výpis volání modulů, které vedly k chybě. Z nich je pak možno identifikovat který ovladač popř. modul jádra způsobuje problémy. Rád bych podotknul, že VŠECHNY níže uvedené chyby můžou mít příčinu v selhávajícím hardware. Zejména pak ve vadné paměti (přetaktované, nebo s příliš agresivním časováním), přetaktovaném nebo přehřívajícím se procesoru, nebo v přetaktované PCI a AGP sběrnici. Poznamenejme, že další část článku se týká pouze operačních systémů založených na jádře NT (Tedy Windows NT, 2000 a XP).

Modrou "obrazovku smrti" BSOD znají snad všichni uživatelé Windows. Pro nás bude nejdůležitější vrchní řádek, který má pro většinu chyb tvar:

***STOP číslo_chyby (parametr1,parametr2,parametr3,parametr4)

Dále pro nás bude zajímavá tabulka dole-výpis naposledy volaných modulů.

Poznámka: Svůj "BSOD" má téměř každý operační systém (Majitelé Amig si jistě pamatují na hlášku Guru meditation, na Linuxu zase jádro napíše lakonické Oops, Kernel panic.) tak proč se všichni rozčilují zrovna nad tím "Windowsím"? ;-)

Stop 0x0A       IRQ_NOT_LESS_OR_EQUAL

Proces nebo ovladač v režimu jádra se pokusil číst/zapisovat do paměti, ke které nemá oprávnění. Většinou se jedná o chybu v ovladači. Z výpisu modulů zjistíme viníka. Pokud se chyba projeví hned při startu vindows je potřeba ve startovním menu zvolit nouzový režim a posledně instalovaný ovladač odstranit. Samostatná kapitola je svázána se vznikem této chyby během instalace. Microsoft doporučuje vypnout v BIOSu před instalaci PnP, antivir, Shadow Memory (paměť překopirována z ROM zařízení do RAM, její čtení je pak mnohem rychlejší), vypnutí cache disku a dokonce i procesoru. Pokud ani to nepomůže pak se doporučuje před instalací vytáhnout všechny rozšiřující karty.

Stop 0x1E       KMODE_EXCEPTION_NOT_HANDLED

Nezpracována výjimka v režimu jádra. Podobně jako u chyby 0x0A se většinou jedná o chybu v ovladači zařízení nebo v hardware (mnohem častěji než v případe 0x1E).

Stop 0x24        NTFS_FILE_SYSTEM

Poškození datové integrity NTFS svazku. Chyba diskového subsystému, přetaktovaná PCI sběrnice nebo poškození souborového systému virem.

Stop 0x50        PAGE_FAULT_IN_NONPAGED_AREA

Požadavek na čtení/zápis neexistující stránky z nestránkované paměti. Nestránkovaná paměť je za všech okolností uložená ve fyzické paměti, nikdy v odkládacím souboru. Může být matoucí že nestránkovaná (nonpaged) paměť má stránky (pages). Přesnější by byl asi překlad "neodstránkovatelná" paměť ale uznejte, že to je příšerné slovo. Většinou zapříčiněno chybou ovladače zařízení.

Stop 0x77        KERNEL_STACK_INPAGE_ERROR
Stop 0x7A       Kernel_Data_Inpage_Error

Chyby čtení z odkládacího souboru.

Přesnější příčinu zjistíme z druhého parametru:

0xC0000008   STATUS_INVALID_HANDLE - neplatný manipulátor (interní číslo identifikující zařízení, soubory atd.),
0xC000009A   STATUS_INSUFFICIENT_RESOURCES - požadavek ovladače zařízení na větší množství nestránkované paměti než je k dispozici,
0xC000009C   STATUS_DEVICE_DATA_ERROR - nejčastěji fyzické poškození záznamového media,
0xC000009D   STATUS_DEVICE_NOT_CONNECTED - zařízení nepřipojeno (překontrolujte zda se neodpojil SCSI nebo IDE kabel),
0xC000016A   STATUS_DISK_OPERATION_FAILED - nejčastěji fyzické poškození zaznamového media a/nebo řadiče,
0xC0000185   STATUS_IO_DEVICE_ERROR - nejčastěji způsobeno špatným nebo chybějícim terminátorem na SCSI sběrnici.

Stop 0x7B       Inaccessible Boot Device

Patří k "nejméně příjemným" chybám jelikož se kvůli ní většinou nejde již vůbec dostat do Windows ani v nouzovém režimu a pomůže jen přeinstalace. Touto chybovou hláškou nám systém oznamuje, že po zavedení jádra nemůže přistoupit k zařízení, na kterém jsou uloženy systémové soubory. Většinou se jedná o situaci, kdy v počítači vyměníme RAID nebo SCSI řadič na jiný typ nebo použijeme novou desku s odlišnou čipovou sadou. Pokud tato chyba nastane během instalace, pravděpodobně jsme zapomněli nainstalovat ovladač pro řadič disku.Pro úplnost ještě uvedu seznam dalšich možných příčin vzniku chyby: vir v boot sektoru, konflikt IRQ nebo I/O zařízení, poškození souborového systému, poškození registru Windows.

Stop 0x7F       EXPECTED_KERNEL_MODE_TRAP

Podle prvního parametru poznáme zda se jedná o chybu:

Dělení nulou                          0x00000000
Aritmetické přetečení             0x00000004
Chyba operace BOUNDS        0x00000005
Neplatný op. kód                   0x00000006
Dvojitá chyba                        0x00000008

Jedná se tedy o translaci chyb 0,4,5,6 a 8 pokud nastanou v režimu jádra. "Microsofti" tvrdí, že se jedná téměř výhradně o chyby hardware - ve většině případů se jde o problém s pamětí nebo procesorem. Ja bych přeci jen možnost softwarové chyby v jádře nebo v ovladačích v režimu jádra úplně nevylučoval. Speciálně v případě chyby 8 se může jednat o přetečení zásobníku (Ukládají se tam návratové proměnné, parametry a lokální proměnné funkcí. Přetečeni vznikne většinou z důvodu zacyklení programu.). V případě chyby 6 je chyba hardware opravdu téměř jistá.

Stop 0x9c

Procesor detekoval hardwarovou chybu a vygeneroval výjimku MCE (Machine Check Exception). Chyba se vyskytuje zřídkakdy jelikož procesor může detekovat jen zlomek chyb. Příčina s největší pravděpodobností leží ve vadném hardware.

Toť celý seznam nejčastěji se vyskytujících chyb. Přeji mnoho příjemných chvil strávených nad bádáním a zkoumáním BSOD a jejich. příčin ;-)

Michal Kwolek

Diskuze (46) Další článek: Apple chystá překvapení, zřejmě LCD iMac

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , ,