Obsluha přerušení, výjimek a systémových volání.
Thursday, May 30, 2013
8:26 AM
Zdroj: [link]
[link]
Přerušení
metoda pro asynchronní obsluhu událostí, kdy procesor přeruší vykonávání sledu instrukcí, vykoná obsluhu přerušení a pak pokračuje.
vnitřní - vyvolané procesorem (problém se zpracováním instrukcí, dělení 0, výpadek stránky)
Také nazývané synchronní, a to proto, že CPU jej vyvolá až po dokončení aktuálně vykonávané instrukce, Intelovský manuál je nazývá Exception
vnější - hardwarové, přichází z V/V zařízení, mají přidělena čísla IRQ (Interrupt Request)
pro signalizaci přerušení– kanály přerušení, reprezentovány čísly IRQ, na jednom IRQ kanálu může být napojeno více zařízení (= sdílený kanál, sdílené IRQ) 
Také nazývané asynchronní, a to proto, že závisí na ticích časovače a může nastat v době kdy CPU právě vykonává nějakou instrukci, Intelovský manuál je nazývá Interrupt
softwarové - speciální instrukce INT 0x80 nebo SYSENTER (SYSCALL)
Další dělení je na maskovatelná a nemaskovatelná
Interrupts:
 Maskable interrupts: All Interrupt Requests (IRQs) issued by I/O devices give rise to maskable interrupts . A maskable interrupt can be in two states: masked or unmasked; a masked interrupt is ignored by the control unit as long as it remains masked.
 Nonmaskable interrupts: Only a few critical events (such as hardware failures) give rise to nonmaskable interrupts . Nonmaskable interrupts are always recognized by the CPU.
Přerušení mají priority - obsluha přerušení může být přerušena přerušením s vyšší prioritou :) - pozn. Priority z hlediska kernelu jsou jen low a high, tedy přerušitelné a nepřerušitelné. APIC (Advanced Programmable Interrupt Controller ale priority podporuje, takže priority přerušení jako takové Linux nikde neřeší, ale nechává to na hardware (APIC je v každém CPU).
The Linux kernel is reentrant (like all UNIX ones), which simply means that multiple processes can be executed by the CPU. He doesn't have to wait till a disk access read is handled by the deadly slow HDD controller, the CPU can process some other stuff until the disk access is finished (which itself will trigger an interrupt if so).
Generally, an interrupt can be interrupted by an other interrupt (preemption), that's called 'Nested Execution'. Depending on the architecture, there are still some critical functions which have to run without interruption (non-preemptive) by completely disabling interrupts. On x86, these are some time relevant functions (time.c, hpet.c) and some xen stuff. 
There are only two priority levels concerning interrupts: 'enable all interrupts' or 'disable all interrupts', so I guess your "high priority interrupt" is the second one. This is the only behavior the Linux kernel knows concerning interrupt priorities and has nothing to do with real-time extensions.
If an interruptible interrupt (your "low priority interrupt") gets interrupted by an other interrupt ("high" or "low"), the kernel saves the old execution code of the interrupted interrupt and starts to process the new interrupt. This "nesting" can happen multiple times and thus can create multiple levels of interrupted interrupts. Afterwards, the kernel reloads the saved code from the old interrupt and tries to finish the old one.
From <[link]> 
Přerušení je obecně asynchronní vzhledem k přerušenému procesu 
Zpracování přerušení nesmí způsobit čekání, přerušený proces zůstává ve stavu běžící 
čas zpracování přerušení je započítán přerušenému procesu, při zpracování se tedy přistupuje do jeho záznamu proc
Obsluha:
1) uloží IRQ (Interrupt ReQuest) a obsah registrů
2) pošle potvrzení PIC (Programmable Interrupt Controller), který zajišťuje provoz přerušení
3) modul pro obsluhu přerušení (Interrupt Handler) vykoná obsluhu přerušení
4) ukončí skokem na ret_from_intr()
synchronní s procesem (vznikají v důsledku událostí způsobených vykonáváním procesu)
Stejné jako u přerušení, 80x86 procesory mají přibližně 20 definovaných výjimek, každá je zpracována přiřazeným exception handlerem - ten většinou nedělá nic jiného než že pošle signál procesu, který výjimku způsobil, kernel musí poskytnout exception handler pro každou definovanou výjimku, příklady výjimek i s jejich číslem: 0 - Divide Error = dělení nulou, 1 - Debug, 4 - Overflow = přetečení…
1) uloží obsah registrů
2) zpracuje výjimku (funkce v jazyku C)
pošle signál procesu
zpracuje žádost o stránku
3) ukončí se voláním funkce ret_from_exception()
Vektor přerušení
 - 0-31 vnitřní přerušení (výjimky), 32 - 255 IRQ přerušení
Vektor přerušení u x86 se nazývá IDT (Interrupt Descriptor Table) - tabulka, která přiřazuje obslužnou rutinu ke každému přerušení
mechanismus pro volání funkcí operačního systému aplikacemi
v standardní knihovně jazyka C je pro každé systémové volání obálková procedura, řízení se předá softwarovým přerušením proceduře jádra syscall()
system_call - jedna pro všechny služby, požadovaná služba se odlišuje parametrem procedury, který se nazývá číslo systémového volání
Obsluha:
system_call:
1) uloží obsah registrů (HW kontext)
2) zavolá odpovídající funkci (v jazyku C)
3) ukončí se voláním ret_from_sys_call()
Int 0x80 je legacy instrukce, funguje jen u 32 bit systému a dnes se nepoužívá
syscall is default way of entering kernel mode on x86-64. This instruction is not available in 32 bit modes of operation on Intel processors.
sysenter is an instruction most frequently used to invoke system calls in 32 bit modes of operation. It is similar to syscall, a bit more difficult to use though, but that is kernel's concern.
int 0x80 is a legacy way to invoke a system call and should be avoided.
Preferable way to invoke a system call is to use VDSO, a part of memory mapped in each process address space that allow to use system calls more efficiently (for example, by not entering kernel mode in some cases at all). VDSO also takes care of more difficult, in comparison to the legacy int 0x80 way, handling of syscall or sysenter instructions.
From <[link]> 
VDSOs (Virtual Dynamically linked Shared Objects) are a way to export kernel space routines to user space applications, using standard mechanisms for linking and loading (i.e. standard ELF format).
It helps to reduce the calling overhead on simple kernel routines, and also can work as a way to select the best system call method on some architectures.
An advantage over other methods is that such exported routines can provide proper DWARF debugging information.
Implementation generally implies hooks in the dynamic linker to find the VDSOs.
From <[link]> 
(z diskuse [link])
From <[link]> 
je dulezity registr idtr - obsahuje poiner na tabulku preruseni. prijde preruseni od hardware, dostane se po dratu do i/o apic, ten ho prelozi a ziska cislo preruseni - koukne do tabulky a podle priority v tabulce ho preposle APIC v jadru ktere je uvedeno v te tabulce u toho preruseni. to konkretni jadro dostane preruseni po intrl (interrupt line) a pushne vse co dela na zasobnik, prepne mod do Ring 0 (rezim jadra je jen mod opravneni v CPU, ring 0 znamena ze ti CPU umozni delat cokoli, ring 3 je mod kde bezi aplikace a pamet je omezena jen na tu ktera je pridelena procesu), CPU v tomhle rezimu jadra koukne na IDTR registr kde je adresa vektoru preruseni, pripocte k te adrese 31 (vnitrni preruseni CPU jsou na zacatku vektoru preruseni, pak az jsou ty hardwarovy), koukne kam to ukazuje a dostane pointer na obsluhu preruseni kam taky skoci (porad v rezimu jadra). Ta obsluha muze byt v driveru (interrupt request handler si registruje driver pri zavedeni a je to jen prepsani te adresy ve vektoru preruseni, popr. kdyz ma vic preruseni stejny cislo tak tam je ulozen spojovy seznam a zkousi se ty handlery pekne postupne). obsluha preruseni musi byt co nejkratsi a na konci se musi zavolat instrukce iret, ktera koukne na zasobnik jadra a podle toho co tam uvidi bud vrati rizeni zpet do procesu kterej byl prerusenej, nebo v pripade zanorenyo preruseni vrati obsluhu predchozimu preruseni. Pokud je preruseni !na dlouho!, linux v jeho obsluze jen vyvola nejaky tasklet (lwp proces v jadre) a necha obsluhu na pozdeji (linux checkuje jestli nejake tasklety cekaji a obsluhuje je napr. pri prepinani do/z rezimu jadra, ale takovych mist je v kernelu pry vic.