1. Reaalitilan muistinhallinta
2. Johdanto suojattuun tilaan
3. Suojatun tilan muistinhallinta
4. Keskeytykset ja poikkeukset

Katso myös:
1. Prashant TR:n laaja-alainen ja havainnollinen suojattua tilaa käsittelevä opas
2. Chris Giesen opas suojatusta tilasta

Keskeytykset ja poikkeukset

Tekijä: Yariv Kaplan
Suomentanut Jouni Kähkönen 21.4.2005, 21.9.2005, 24.3.2007, 30.4.2007

Johdanto

Tietokoneen toimintaa ohjataan suorittimen lisäksi monin eri laittein. Esimerkiksi sarjaportin tietoliikennettä ohjaa emolevyn (täsmällisemmin ASIC-yksikön) Intel 8251A -piiri (tai uusissa koneissa 16550AF-piiri), ja näppäimistöä ohjaa 8042A-mikrosuoritin.

Koska laitteet toimivat kaikki omilla nopeuksillaan, tarvitaan jokin menetelmä suorittimen toiminnan ja muiden laitteiden synkronoimiseen. Eräs ratkaisu on, että suoritin kiertää nopeasti silmukkaa kysyen koko ajan laitteilta niiden senhetkistä tilaa (menetelmää kutsutaan kiertokyselyksi, engl. polling). Kun tiedot on noudettavissa laitteelta, suoritin voi lukea ja käsitellä saapuvat tavut. Toimiihan tämäkin menetelmä, mutta se on monin tavoin ongelmallinen. Ensinnäkin se on todella tuhlaava käsittelyn tehokkuuden suhteen, sillä suoritin joutuu olemaan koko ajan varattuna lukiessaan oheislaitteiden tiloja, vaikka se voisi sen ajan suorittaa jotain hyödyllistä koodia. Toisekseen datan siirtotahdin ollessa hyvin suuri suoritin saattaa hävittää laitteilta saapuvaa dataa.

Täten keksittiin toisenlainen toimintamalli. Laitteilta ei pyydetä koko ajan vastausta, vaan ne ovat itse vastuussa tilansa ilmoittamisesta suorittimelle. Tarvitessaan huomiota suorittimelta laite vain lähettää sähkösignaalin (ns. laitteistokeskeytyksen, engl. hardware interrupt) emolevyllä sijaitsevan keskeytysohjainpiirin tiettyyn pinniin.

Keskeytysohjain toimii välikappaleena suorittimen ja laitteiden välillä. Sen vastuulla on ilmoittaa suorittimelle siitä, että jokin laite tarvitsee siltä välitöntä huomiota. Tällaisessa tapauksessa suoritin keskeyttää senhetkisen toimintansa ja siirtyy suorittamaan toimintoa (eli keskeytyksenkäsittelijää, engl. interrupt handler), joka on aikaisemmin yhdistetty kutsuvaan laitteeseen (tai tarkalleen sanottuna laitteen keskeytysvektoriin yhdistettyyn laitteeseen).

Ohjelmistokeskeytyksillä on laitteistokeskeytysten tavoin tärkeä asema PC:n perustoiminnassa. Nämä keskeytykset ovat pikemminkin synkronisia kuin asynkronisia, sillä ne ovat itsensä suorittimen aikaansaamia (suorittimen tavatessa koodivuossa INT-käskyn). Käyttöjärjestelmät julkaisevat sisäiset funktionsa ohjelmistokeskeytyksillä, jotta sovellukset voivat käyttää järjestelmän palveluita hyödyksi.

Poikkeukset (engl. exceptions) ovat erityisen kaltaisia ohjelmistokeskeytyksiä. Suoritin aiheuttaa poikkeuksen, kun jokin odottamaton ja kriittinen tapahtuma ilmenee. Esimerkiksi sivutushäiriöpoikkeus (keskeytys 14, engl. page fault exception) laukaistaan suorittimen yrittäessä käyttää käyttämättömäksi merkittyä sivua. Poikkeuksenkäsittelijä voi sitten ladata sivun levyltä eli näennäismuistista takaisin muistiin ja suorittaa poikkeuksen aiheuttaneen käskyn uudestaan.

Suoritin osaa aiheuttaa kolmenlaisia poikkeuksia: vikoja (fault), ohjelmallisia keskeytyksiä (trap) ja virhelopetuksia (abort). Vikapoikkeuksen sattuessa pinoon viedyt CS- ja (E)IP-rekisterit osoittavat poikkeuksen aiheuttaneen käskyn osoitteeseen. Tämä antaa poikkeuksenkäsittelijälle mahdollisuuden korjata poikkeuksen aiheuttaneen ehdon, ennen kuin vian aiheuttanut käsky suoritetaan uudelleen. Ohjelmalliset keskeytykset ovat hieman samankaltaisia kuin keskeytykset. Ohjelmalliset keskeytykset nimittäin panevat suorittimen tallentamaan pinoon seuraavan käskyn osoitteen. Ne myös keskeyttävät häiriköineen sovelluksen ja määrittelevät häiriön tehneen käskyn sijainnin, jotta ne voitaisiin näyttää käyttäjälle peruuttamattomien vakavien virheiden ilmetessä (kuten laitteistovirheet ja laittomat järjestelmätaulut).

Reaalitila

Ohjelmistokeskeytykset

Jos olet joskus ohjelmoinut DOS-järjestelmällä, tietänet INT 21h -liittymällä olleen tärkeä merkitys sovellusten yhdistämisessä käyttöjärjestelmäpalveluihin. Esimerkiksi käyttöjärjestelmän tiedostonavauskomennon käyttö vaatii INT 21h -keskeytyksen kutsumista sopivin rekisteriparametrein.

BIOS eli Basic Input Output System käyttää samankaltaista ohjelmistokommunikointijärjestelmää. INT 10h, 13h ja 16h ovat näyttöä, levyohjainta ja näppäimistöä ohjaavia BIOS-järjestelmän sisäisiä toimintoja. Laitteiston välittömän käytön sijasta DOS ohjaa järjestelmän toimintaa BIOS-palveluilla. Windows NT ja muut uudenaikaiset käyttöjärjestelmät eivät ole BIOS-järjestelmästä riippuvaisia, jotta PC-laitteita voitaisiin käyttää nopeammin keinoin eli laitteistoajurein.

Hypätessään INT-käskyyn suoritin heittää pinoon seuraavaksi suoritettavan käskyn osoitteen (eli CS- ja IP-rekisterit) sekä lippurekisterin sisällön ja siirtyy sitten suorittamaan keskeytyksenkäsittelijän koodia. Näin varmistetaan, että suoritin voi käsittelijän koodin suoritettuaan palata automaattisesti alkuperäiseen koodivuohon (eli koodiin, jota oltiin suorittamassa ennen keskeytyksen aloittamista).

Tässä yksityiskohtainen luettelo suorittimen eri vaiheista INT-käskyn aikana:

  1. Siirtää liput, CS- ja IP-rekisterit pinoon (tässä järjestyksessä).
  2. Kertoo keskeytyksen numeron luvulla 4 ja käyttää kertolaskun tuloa siirroksena fyysisen osoiteavaruuden alussa sijaitsevaan keskeytystauluun.
  3. Hakee taulutietueesta keskeytyksenkäsittelijän etäosoitteen eli arvot CS- ja IP-rekistereille.
  4. Poistaa keskeytykset käytöstä (huomaa, että mikäli haluat laitteistokeskeytysten toimivan silloin, kun suoritin suorittaa keskeytyksenkäsittelijän sisältämää koodia, käsittelijän koodin alussa on suoritettava STI-käsky).
  5. Hyppää suorittamaan käsittelijää.
  6. Kun käsittelijän koodi on saatu päätökseen (eli kun IRET-käsky on suoritettu), pinosta haetaan CS-, IP- ja lippurekisterien arvot, ja suoritettava sovellus saa taas jatkaa koodinsa suorittamista.

Monet sovellukset (erityisesti TSR- eli Terminate and Stay Resident -ohjelmat) jättävät muistiin ohjelmistokeskeytyksiä tarjotakseen lisäpalveluja Dos- ja BIOS-järjestelmien palvelujen lisäksi. Eräs hyvä esimerkki on Netware 3.1, joka lisää keskeytyksiä INT 21h -keskeytykseen verkon tiedostotoimintojen tukemiseen (kuten etäkoneella olevan tiedoston lukemiseen). Muut koodinpätkät, etenkin laiteajurit, luovat laitteistokeskeytyksiä valvoakseen eri laitteita ja varmistaakseen niiden virheettömän toiminnan.

Luodakseen keskeytyksen ohjelman tarvitsee vain panna keskeytystaulussa sijaitsevaan tietueeseen oman keskeytyksenkäsittelijänsä osoite. Kun tätä keskeytystä joskus kutsutaan, suoritin suorittaa keskeytyksenkäsittelijän itsestään. Hyvä ohjelmointikäytäntö on panna keskeytyksenkäsittelijäfunktion sisään kutsu edelliseen käsittelijään. Näin varmistutaan siitä, että kaikki aikaisemmin luodut keskeytykset saavat tilaisuuden käsitellä tulevia keskeytyksiä.

Huomaa, että ladattaessa sovellusta, joka kutsuu käyttöjärjestelmän palveluja ohjelmistokeskeytyksin, sovelluskoodin muistiosoitteita ei tarvitse muuttaa vastaamaan käyttöjärjestelmäpalvelujen todellisia muistiosoitteita. Siten käyttöjärjestelmä voi vapaasti siirtää palvelunsa uuteen paikkaan muistissa yksinkertaisesti päivittämällä vastaavat keskeytystaulun tietueet uusilla osoitteilla.

Laitteistokeskeytykset

Laitteistokeskeytykset (engl. hardware interrupts) eivät poikkea käyttäytymiseltään muista keskeytyksistä suuresti. Kuitenkin tarkastellessamme laitteistokeskeytyksen kulkemaa reittiä voimme todeta laitteistokeskeytysten poistuneen laitteesta ennen saapumistaan suorittimelle. On siis huomioitava toimet, jotka keskeytyksenkäsittelijä (tai 8259A, jos se kuulostaa paremmalta) saattaa tehdä.

Suorittaessaan INT-käskyn suoritin noutaa keskeytyskoodin juurikin opkoodilta. Suoritin osoittaa tällä arvolla myöhemmin IVT-tauluun (engl. interrupt vector table) ja etsii keskeytyksenkäsittelijän osoitteen. Toisin sanoen havaitessaan laitteistokeskeytyksen keskeytysohjain lähettää keskeytyskoodin suorittimelle väyliä pitkin. Vastaanotettuaan koodin (joko INT-opkoodilta tai keskeytysohjaimelta) suorittimen suorittamat vaiheet ovat edellä mainitun kaltaisia.

Taulukko 1 kuvaa keskeytyksenohjauspiirien käyttämiä keskeytysvektoreita eri käyttöjärjestelmillä:

Käyttöjärjestelmä 8259A-piirin käyttämät vektorit 8259A-alipiirin käyttämät piirit
DOS
8h - Fh
70h - 77h
Windows 95 / 98
50h - 57h
58h - 5Fh
Windows NT
30h - 37h
38h - 3Fh
Taulukko 1 - 8259A-piirien käyttämät keskeytysvektorit

Poikkeukset

Reaalitila tukee seuraavia poikkeuksia:

Poikkeus Vektori Ehto
Jako nollalla
0
Yritys suorittaa DIV- tai IDIV-käsky jakajan ollen nolla.
Virheenkorjaus tai yksivaihe (engl. single step)
1
Yhdessä virheenkorjausrekisterien kanssa kertoo keskeytyskohdan kohtaamisesta. Suoritin myös suorittaa tämän keskeytyksen aina jokaisen käskyn suorittamisen jälkeen, mikäli TRAP-lippu on päällä.
Keskeytyskohta (engl. break point)
3
INT 3 -käsky aiheuttaa tämän poikkeuksen. Koska tämän käskyn opkoodi on vain yhden tavun kokoinen, virheenkorjaussovellukset käyttävät käskyä usein asettaakseen keskeytyskohdan sovelluksen koodiin. Virheenkorjaussovelluksen on vain vaihdettava käskyn ensimmäinen tavu INT 3 -keskeytyksen opkoodiin (11001100b) ja odotettava keskeytyskohtapoikkeuksen ilmenemistä. Jatkaessaan suoritusta poikkeuksenkäsittelijä ei vielä palaa sovellukseen, jonka virheitä jäljitetään, vaan sitä ennen virheenkorjaussovellus muuttaa INT 3 -käskyn opkoodiksi aikaisemmin ylikirjoitetun tavun ja suorittaa IRET-käskyn (engl. interrupt return).
Ylivuoto
4
Suorittaessaan aritmeettisia käskyjä, joilla on etumerkillisiä operandeja, suoritin panee OF-lipun päälle ilmoittaakseen ylivuodon tapahtuneen. INTO-käsky tarkistaa tämän lipun arvon. Jos lippu on päällä, aiheutetaan poikkeus.
Raja-arvojen tarkastus (engl. bounds check)
5
BOUND-käskyllä määritetään taulukon (engl. array) indeksin raja-arvo, jota ei saa ylittää. Jos raja-arvo ylitetään, suoritin aiheuttaa poikkeuksen.
Virheellinen opkoodi
6
Tapahtuu suorittimen käyttäessä varattua opkoodia tai käsitellessä LOCK-etuliitettä väärin. Voi myös ilmaista opkoodin jälkeen ilmenevän virheellisen operandin.
Laite ei käytettävissä
7
Yritys suorittaa liukulukukäskyä, kun matematiikkasuoritinta ei ole asennettu. Nollaa CR0-rekisterin EM-bitti, mikäli haluat poistaa tämän poikkeuksen käytöstä.
Kaksoishäiriö (engl. double fault
8
Tapahtuu suorittaessa keskeytystä, jolla ei ole tietuetta IVT-taulussa tai aiheutettaessa poikkeus suorittimen suorittaessa vielä aikaisemmin käynnistettyä poikkeuksenkäsittelijää.
Pinopoikkeus
12
Tapahtuu, kun pinoon liittyvä toiminto ylittää siirroksen FFFFh, tai kun SS-rekisteriin ladataan käyttämättömäksi merkitty segmentti.
CS-, DS-, ES-, FS- tai GS-segmentin ylivuoto
13
Word-tyyppisen siirroksen käyttö siirroksen arvon ollessa FFFFh tai yritys suorittaa koodia koodisegmentin raja-arvon ulkopuolella.
Liukulukuvirhe
16
Virhe matematiikkasuorittimen yhteydessä (jako nollalla, alivuoto, ylivuoto yms).
Taulukko 2 - Reaalitilan poikkeukset

Muut poikkeukset ovat olemassa vain 8086-suorittimen näennäis- eli virtuaalitilassa:

Poikkeus Vektori Ehto
Virheellinen TS- eli
Task State -segmentti
10
Kertoo, että jokin tehtävän vaihdon aikana tehdyistä tarkastuksista epäonnistui.
Segmentti merkitty käyttämättömäksi
11
Minkä tahansa segmenttirekisterin lataaminen selektorilla, joka osoittaa käyttämättömäksi merkittyyn segmenttiin.
Sivutusvirhe
14
Järjestelmävalvojatason sivun käyttö käyttäjätason koodista käsin tai käyttämättömäksi merkityn sivun käyttö.
Ryhmittelytarkistus
(engl. Alignment Check)
17
Ryhmittelemättömän muistisijainnin käyttö (voi ilmetä vain ring 3 -tason koodia suoritettaessa)
Taulukko 3 - Virtuaalitilan poikkeukset

Suojattu tila

Keskeytystenkäsittely suojatussa tilassa vaatii erinäisen taulun asettamista muistiin. Tämä taulu on nimeltään IDT (Interrupt Descriptor Table). IDT poikkeaa hieman reaalitilan keskeytysvektoritaulusta. Suojatussa tilassa IDT-taulu ei ole paikallaan fyysisessä osoitteessa 0, vaan se voi siirtyä lineaarisen osoiteavaruuden sisällä täysin vapaasti. Reaalitilassakin IVT-taulun sijaintia voi vaihtaa, mutta se ei ole kuitenkaan yhteensopiva 8086-suorittimen arkkitehtuurin kanssa. IDT-taulun lineaarisen osoitteen määrää IDTR-rekisteriin LIDT-käskyllä asetettu arvo. IDT-taulun jokainen tietue on 8 tavun kokoinen (IVT-taulussa vastaava tietueen koko on 4 tavua). Nämä tietueet voivat sisältää jonkin näistä kolmesta porttideskriptorista:

Seuraava kuvio kuvaa ohjelmallisen keskeytysportin tietueen sisäisen rakenteen:


Kuvio 1 - Ohjelmallisen keskeytysportin tietueen rakenne

Keskeytysporteilla eli keskeytyksillä ja ohjelmallisilla keskeytyksillä on paljon yhteistä. Niillä molemmilla suoritetaan ohjauksensiirtoja (engl. control transfer) eri etuoikeustasojen välillä. Näissä porttideskriptoreissa määriteltyjä selektori- ja siirroskenttiä käytetään keskeytyksenkäsittelijän koodin paikantamiseen ja suorittamiseen. Ohjauksensiirto sallitaan vain koodille, joka sijaitsee samalla tai ylemmällä etuoikeustasolla.

Ohjelmistokeskeytykset

Monet suojatun tilan käyttöjärjestelmät käyttävät yhä ohjelmistokeskeytyksiä sisäisten palvelujensa julkaisemiseen. Useimmat näistä rajapinnoista ovat kuitenkin funktioiden takana eikä niitä voida käyttää suoraan (se on tosin mahdollista muttei suositeltavaa). Esimerkiksi Windows NT mahdollistaa käyttäjätilan ja ydintilan osien välisen ohjauksensiirron käyttämällä dokumentoimatonta keskeytystä 2Eh. Kun oikeuttamaton Windows-sovellus kutsuu API-funktiota, järjestelmä reitittää kutsun, ellei se kohtaa INT 2Eh -käskyä. Tätä keskeytystä vastaava IDT-portti osoittaa ntoskrnl-ytimen sisällä olevaan käsittelijään, joka suorittaa vaaditut, etuoikeutetut toimenpiteet ohjelman puolesta. Windows 95 ja 98 käyttävät vastaavanlaista tekniikkaa käyttäjä- ja ydintilojen välillä vaihteluun. Tosin Windows 95 ja 98 tukeutuvat INT 2Eh -keskeytyksen sijasta INT 30h -keskeytykseen.

Laitteistokeskeytykset

Laitteistokeskeytykset käyttäytyvät suojatussa tilassa reaalitilan kappaleessa kuvatulla tavalla. Ainoa merkittävä ero on se, että suojatussa tilassa suoritin käyttää avuksi omaa IDT-tauluaan eikä etsiskele keskeytyksenkäsittelijän osoitetta reaalitilan IVT-taulusta.

Poikkeukset

Suurin osa edellisten kappaleiden tiedoista koskee suojatussakin tilaa. Poikkeuksella 13 (General Protection Fault -poikkeus) on kuitenkin suojatussa tilassa laajempi merkitys; sillä ilmaistaan muutakin kuin reaalitilassa määriteltyjä asioita.

Se on siinä! Lisää tietoa suojatun tilan keskeytyksistä ja poikkeuksista saat Intelin "Pentium-suorittimen ohjekirjasta".

Voit halutessasi tutustua myös Intelin ohjekirjoihin.


Copyright © 1997, 1998 Yariv Kaplan
yariv(at)internals(dot)com
Suomennos: Jouni Kähkönen, käyttäjä=kajouni, palvelin=mbnet.fi

Avainsanat: suojattu tila protected mode 386 80386 x86 os operating system developing reaalitila käyttöjärjestelmäohjelmointi käyttöjärjestelmäohjelmoinnin ohjelmointi ohjelmoinnin operating system development memory management interrupts ints keskeytykset poikkeukset keskeytys poikkeus interrupts expections exceptions suoritin suorittimen suoritinta suorittimien suoritinten prosessori prosessorin prosessoria prosessoreiden sovellus sovelluksen sovellusta ohjelma ohjelman ohjelmaa application program ohjauksensiirto ohjauksen siirto control transfer