KURZUS: Számítógépes folyamatirányítás
MODUL: A számítógép
3.4. lecke: Kiemelkedő jelentőségű programozástechnikai elemek 2.
Cél: A lecke célja, hogy a tananyag felhasználója | |||
| |||
Követelmények: Ön akkor sajátította el megfelelően a tananyagot, ha | |||
| |||
Időszükséglet: 2 óra | |||
Kulcsfogalmak: | |||
| |||
1. A megszakítás (interrupt) | |||
Ha van valami, ami a folyamatirányító számítógépekkel kapcsolatban a legfontosabb jellemzőnek, illetve követelménynek mondható, akkor az a megszakítás, illetve a megszakításrendszer megléte. | |||
Jegyezze meg, hogy mit értünk megszakítás és megszakítási rutin alatt; | |||
A megszakítás azt jelenti, hogy a számítógép egy tőle független, külső eseményre azonnal és úgy reagál, hogy az éppen futó programot felfüggeszti és egy olyan programot hajt végre, amely az eseményre vonatkozó válaszreakció leírását tartalmazza. Ezt a programot megszakításirutinnak (IT-rutin) szokás nevezni. A megszakítási rutin lefutása után a számítógép visszatérhet eredeti tevékenységéhez, azaz folytathatja a korábban felfüggesztett program végrehajtását. | |||
Egy folyamatirányító számítógépnek legalább egy megszakítást, az óra-interrutot feltétlenül kezelnie kell. Az óra-interrupt egy periodikusan jelentkező impulzus, amely gép működését a külső, valós időhöz szinkronizálja. Az erre adandó válaszreakció - sok egyéb mellett - az, hogy a számítógép aktualizálja a belső, un. szoftver-órát. Erről és egyebekről a 6. modulban még bőven lesz szó. | |||
Az egyes megszakítási okok fontossági sorrendbe állíthatók, vagyis minden okhoz prioritás rendelhető. Egy magasabb prioritású megszakítási ok megszakíthat egy alacsonyabb szinten futó (kisebb prioritású okhoz tartozó) megszakítási rutint is (1. ábra). | |||
| |||
Vannak olyan processzorok, amelyek eleve prioritásos megszakításrendszerrel rendelkeznek, vannak olyanok, amelyekhez megfelelő külső hardver-eszközt kell illeszteni a prioritásos kezelés megvalósításához, és vannak olyan esetek, melyeknél a prioritást az operációs rendszer (tehát a szoftver) rendeli az egyes okokhoz. A megszakításrendszerek általános vizsgálatakor sokszor igen nehéz megtalálni azt a határt, ameddig a hardver, és ahonnan a szoftver (az operációs rendszer) szabja meg a működést, ezért itt is konkrét megoldások tanulmányozása ajánlatos. | |||
A legegyszerűbb eset az, amikor egy megszakítás-vezeték van és csak egy megszakítási ok. Ilyenkor a megszakítási folyamat pontosan úgy zajlik le, mint egy szubrutinhívás, csak a hívó utasítás nincs beírva a programba (nem is lehet!), ugyanis itt a hívást nem utasítás, hanem a megszakításjel megjelenése váltja ki. A processzor automatikusan a stackbe menti a megszakított program PC-jét, majd átadja a vezérlést egy adott címre (itt kell kezdődnie a megszakítási rutinnak). A rutin lefut, majd egy RET utasítással a stackből elővett cím alapján visszatér a megszakított programba. Ez a folyamat teljes egészében processzor-szinten zajlik le, sem kiegészítő hardver eszközt, sem az operációs rendszer közreműködését nem igényli. | |||
Ha egy megszakítás-vezeték van, de azon több, különböző okból eredő megszakításkérés jöhet be, akkor azonosítani kell az okot, mert ettől függ a válaszreakció. A processzor itt is elmenti a megszakított program PC-jét és átadja a vezérlést egy címre. Ez a cím azonban most nem a megszakítási rutin kezdőcíme (nem is lehet az, hiszen még nem tudni, melyik rutinnak kell lefutnia), hanem az operációs rendszer (egyik) belépési pontja. Az ok azonosítása az operációs rendszer feladata. Erre két megoldás van: a lekérdezéses (polling) és a vektoros módszer. | |||
| |||
Olyan - az előzőnél direktebb - vektoros megszakítás is van, ahol a megszakításvektor egy CALL-jellegű rövid utasítás kódja, a kódban foglalt implicit címmel. Beérkezésekor a processzor ezt azonnal végrehajtja, mint egy közönséges szubrutinhívást. A visszatérés közvetlenül a megszakított programba történik. Ez a folyamat is teljes egészében processzor-szinten zajlik le, nincs szükség az operációs rendszer közbeékelődésére. | |||
Próbálja meg - ismeretei teljes bevetésével - a lehető legrészletesebben átgondolni a fentebb említett megszakítási folyamatok lejátszódását! Felváltva képzelje magát a processzor, az operációs rendszer, a főprogram és a megszakítási rutin helyébe! Ki, mikor mit csinál? Akkor gondolta át helyesen az eseményeket, ha valóban belátta, ha biztosan meggyőződött arról, hogy a folyamat végén a vezérlés visszakerült a főprogramhoz és az zavartalanul folytatja futását. (Nyugalmas, csendes helyre lesz szüksége...) | |||
A prioritásos megszakításrendszereknek biztosítaniuk kell, hogy egy megszakítás bekövetkeztekor (annak kiszolgálása közben) nála alacsonyabb szintű megszakítások ne juthassanak érvényre. Ez a megszakítások szelektív tiltását jelenti, amely részben hardver-, részben szoftver-eszközökkel valósítható meg. Ennek részleteire itt nem térünk ki. | |||
A megszakítási rutinok formailag közönséges szubrutinok. A szubrutinhívás és a megszakítás között van azonban egy nagyon lényeges, elvi különbség. Az ugyanis, hogy a szubrutinhívás programozott, a megszakítás viszont nem. A programozó a program írásakor pontosan tudja, hogy melyik szubrutint, hol akarja aktivizálni, és azt és ott fogja meghívni. A megszakítást viszont a külvilág aszinkron módon és véletlenszerűen generálja. A programozó erre nem készülhet fel, mert nem láthatja előre, hogy a programját majdan, futás közben mikor, illetve mely ponton fogja egy külső esemény megszakítani. A programozó tehát nem írhatja elő a programban, hogy mi a teendő akkor, ha azt megszakítják. (Ezért nagyon rossz, a lényeget elködösítő kifejezés a "programozott megszakítás".) | |||
Van egy kérlelhetetlenül szigorú elv: okozza bármi a megszakítást, legyen bármilyen a megszakításrendszer, a megszakított programnak nem szabad észrevennie, hogy megszakították. A megszakítás alatt a program ájultan hever, és amikor magához tér, mindent úgy kell találnia, ahogyan ájulata előtt volt, ellenkező esetben a továbbiakban hibásan fog működni. Kevésbé plasztikusan, de pontosabban fogalmazva ez a következőket jelenti. Minden program felépít maga körül egy adatkörnyezetet context), amely a program futása közben, annak hatására változik. A megszakítási rutin ettől idegen, tehát működésével nem szabad, hogy befolyásolja a megszakított program contextjét. Ezért azt megszakításkor el kell menteni és a vezérlés visszaadása előtt vissza kell állítani. A megszakításrendszer kialakításától függően ez vagy az operációs rendszer, vagy a megszakítási rutin feladata, sőt kötelessége. Csak az a kérdés, mi alkotja a contextet, mit kell elmenteni, mert nyilván az egész memóriát nem lehet. A válasz elég egyszerű: minden olyan regiszter tartalmát, amelyet az operációs rendszer és/vagy a megszakítási rutin használ. A kettő együtt valószínűleg mindet használja, úgyhogy legjobb minden regisztert elmenteni. A stack-tartalmakat nem kell, mert az újabb adatok a régiek fölé rétegződnek, így a régiek megmaradnak (nem íródnak felül). Viszont a stack szintjét a megszakítás előtti állapotba kell hozni, tehát a stack-pointer tartalma nem különbözhet a megszakítás előtti értéktől. Végül, a megszakítási rutin nem használhat (pontosabban: nem írhat) olyan memóriaterületet, melyet a program is használ. Ez nem jelentős megszorítás, a mai számítógépekben elég nagy a memória és a megszakítási rutinoknak rendszerint nincs is szükségük nagy munkaterületekre. | |||
2. Az újrahívhatóság (reentrant code) | |||
Jegyezze meg a context és az újrahívhatóság fogalmát; | |||
Ez a fogalom (ha eltekintünk a rekurzív szubrutinhívástól) csak olyan számítógépes rendszerek kapcsán merül fel, ahol virtuálisan párhuzamos módon több program fut egy időben. A számítógépes folyamatirányító rendszerek pontosan ilyenek. | |||
A problémát egy példa kapcsán elemezzük. Tegyük fel, hogy van két program, A és B, valamint egy S szubrutin. A szubrutin olyan műveleteket végez, melyekre mind a két programnak szüksége van, vagyis mindkét program valahol meghívja. Tegyük fel, hogy éppen az A program fut és éppen meghívta a szubrutint, vagyis S most A adataival A-nak dolgozik. Még nem fejezte be a tevékenységét, amikor az operációs rendszer felfüggeszti A futását és B-t engedi futni. B szintén meghívja S-et, akinek a contextje A félig kész adataival van tele. S elkezd B adataival B-nek dolgozni, eközben az A számára korábban készült adatok felülíródnak. Mondjuk S befejezi a munkát B-nek, így B, aki újrahívta S-et, jó eredményeket kap. Most az operációs rendszer visszaadja a vezérlést A-nak, aki előzőleg S-ben futott és természetesen ott is folytatódik a futása. De S contextje most már B adatait tartalmazza, így A számára hibás eredményeket fog előállítani. Azt mondjuk, hogy S ebben az esetben nem volt újrahívható. | |||
Ha S contextje csak a regiszterekre (és a stackre) korlátozódna, vagyis munkaterületként csak ezeket használná, akkor az újrahívás nem járna a fent bemutatott mellékhatással, mert az operációs rendszer két program közti átkapcsoláskor elmenti a felfüggesztett program regisztertartalmait, visszakapcsoláskor pedig visszaállítja. Így amikor S A-nak folytatja a munkát, azokkal az adatokkal folytathatná, amelyekkel abbahagyta, és nem lehetne észrevenni, hogy közben B-nek is dolgozott. Példánkban S contextjének nyilván olyan elemei is voltak, amelyeket átkapcsoláskor nem mentett el az operációs rendszer. Ez pedig csak S által saját célra, munkaterületként lefoglalt fix memóriaterület lehet. | |||
A fentiekből levonható az általános következtetés: ha egy szubrutin munkaterületként csak a regisztereket és a stacket használja, akkor újrahívható, ha fix helyen lévő memóriát is használ, akkor nem. Ha a szubrutinnak szüksége van memóriaterületre, akkor az ne állandó helyen legyen, hanem azt a mindenkori hívó program jelölje ki számára, mert akkor nyilván különböző hívók különböző területeket fognak kijelölni és így nem következhet be ütközés (adat-felülírás). | |||
Megemlítjük még, hogy egy szubrutint akkor is használhat több program, ha nem újrahívható, de akkor szigorúan csak időben egymás után és nem közvetlen hívással, hanem egy - a kölcsönös kizárást biztosító - másfajta mechanizmus segítségével, amiről majd a 6. modulban lesz szó. | |||
3. Az input-output kezelés (I/O) | |||
A leckerész áttanulmányozása után: | |||
| |||
Az input-outputkezelés alatt a számítógép és a perifériák közötti kapcsolat szervezésének módjait értjük. | |||
A számítógépes folyamatirányításban az I/O kezelés fokozott jelentőségre tesz szert azáltal, hogy itt általában lényegesen több perifériát kell kezelni, mint másutt, és az I/O folyamatoknak az egyéb tevékenységekhez viszonyított relatív súlya lényegesen nagyobb, mint más rendszerekben. | |||
A számítógép és a perifériák közötti adatáramlás un. portokon keresztül valósul meg. A portok címezhető logikai elemek, melyek fizikailag a perifériavezérlő egységek regiszterei formájában jelennek meg. Funkcionális szempontból háromféle port van: | |||
| |||
Állapot- és adatport minden perifériához tartozik, vezérlőportja viszont csak a többfunkciós, változtatható üzemmódú, programozható (un. intelligens) perifériáknak van. | |||
Az állapotporton a periféria aktuális állapotával kapcsolatos információ jelenik meg. Ennek egyes bitjei diagnosztikai jelentőségűek, bizonyos periféria-specifikus hibaokokhoz vannak rendelve (pl. nincs papír a nyomtatóban, nincs festék a nyomtatóban, stb.). Mindig van azonban köztük egy - a periféria fajtájától független - általános, univerzális készültség-bit (READY), melynek 1-es értéke a periféria adatátvitelre való alkalmasságát, 0-értéke pedig alkalmatlanságát jelenti. READY=1 esetén a diagnosztikai biteknek nincs jelentőségük. A READY állapot input perifériánál egyben arra is utal, hogy van érvényes adata, amit be lehet olvasni róla, output perifériánál pedig arra, hogy képes fogadni a kiküldött adatot. A állapotport a processzor szempontjából mindig input-jellegű. | |||
A vezérlőporton a periféria számára az aktuális üzemmódot kijelölő és annak paramétereit beállító parancsok küldhetők ki. Például egy mágneslemezes háttértároló vezérlőegységével közölni kell, hogy a processzor írni, vagy olvasni akar, valamint meg kell adni az adat lemezen értelmezett fizikai címeit. A vezérlőport a processzor szempontjából mindig output-jellegű. | |||
Maga az adatforgalom az adatportokon zajlik le. Az adatportok a periféria jellegétől függően lehetnek input- vagy output-portok. | |||
A ki-/bevitel szervezésének három különböző módja van: | |||
| |||
A programozott I/O esetén az átvitelt kezdeményező program leolvassa a kiválasztott periféria állapot-portját és megvizsgálja, hogy a periféria READY-állapotban van-e. Ha igen, végrehajtja az adatátvitelt: bevitel esetén beolvassa az adatport tartalmát, kivitelkor pedig kiküldi az adatot az adatportra.. Ha a periféria nem "kész", a program potenciálisan végtelen várakozási hurokba kerül, egészen addig, amíg a READY-bit 1-es nem lesz. A várakozás ideje alatt a program folyamatosan olvassa az állapotportot és vizsgálja a READY-bitet. Ez az aktív várakozás kitölti a processzor teljes idejét, így az semmilyen hasznos tevékenységet nem tud végezni (holott futtathatna olyan programokat, melyeknek pillanatnyilag nincs szükségük az adott perifériára). Ezért az input/output ilyen szervezése több-felhasználós rendszerekben (és ilyen a folyamatirányító rendszer is) szigorúan tilos. | |||
A megszakításos I/O szervezésnél a program nem várakozhat aktívan a nem-kész perifériára. Az operációs rendszer felfüggeszti a futását és a processzor használatát más programnak engedélyezi. Ha közben a felfüggesztett program által igényelt periféria READY-állapotba kerül, azt megszakítással jelzi. Ekkor az operációs rendszer visszaadja a vezérlést a felfüggesztett programnak, amely most már késedelem nélkül lebonyolíthatja az I/O-műveletet. | |||
A DMA során a processzor már egyáltalán nem vesz részt az adatátvitelben. Egy buszvezérlésre alkalmas (un. intelligens) perifériavezérlő egységet annak vezérlő portján keresztül ellát a szükséges információkkal (az érintett memóriaterület kezdőcíme, az átviendő szavak darabszáma, az átvitel iránya, a periférián értelmezett fizikai címek). Ezek alapján a perifériavezérlő a processzor működésével virtuálisan párhuzamosan (un. cikluslopásokkal), vagy ténylegesen párhuzamosan (olyankor, amikor a processzor éppen belső műveleteket végez és nem igényli a buszt) önállóan lebonyolítja az adatátvitelt. A folyamat befejeződését egy megszakítással jelzi a processzornak. A DMA megvalósíthatóságának három feltétele van: UNIBUS-struktúra, megszakításrendszer megléte, intelligens perifériavezérlő. (A perifériavezérlő intelligenciája a buszvezérlés, valamint az átvitt adatmennyiség nyilvántartásának képességét jelenti.) | |||
Fel szokott merülni a kérdés: melyik jobb: a megszakításos I/O, vagy a DMA? Azt lehet válaszolni, hogy a két szervezési mód nem ugyanarra való. Ha csak néhány szó (bájt) átviteléről van szó, akkor a megszakításos szervezés a jobb, mert a feldolgozó program közvetlenebbül jut az adatokhoz. (Egy-két, vagy tíz-húsz bájtot DMA-val átvinni nevetséges és roppant körülményes lenne.) És arról se feledkezzünk meg, hogy a legtöbb periféria eleve nem alkalmas a DMA-ra. Ugyanakkor, ha nagy adatmennyiség mozgatására van szükség (pl. képernyőfrissítés, lemezműveletek), akkor a DMA jobb, mert sokszorosan gyorsabb. | |||
Lépjen ki a tananyagból! Gondolja át a lecke tartalmát, rekonstruálja a szerkezetét! Vegyen elő egy lapot és írja le a lecke vázlatát! Ne sajnálja az erre fordított időt! Ha gondosan megcsinálja, már majdnem tudja is az anyagot. |
Önellenőrző kérdések | |||||||||||||||||||||||||||
1. Mondja el saját szavaival a megszakítás és a megszakítási ok és a megszakítási rutin fogalmát! | |||||||||||||||||||||||||||
2. Sorolja fel a megszakításkezelés különböző fajtáit és mondja el a megszakítási folyamat lezajlását! (Minden esetben a gyanútlanul futó főprogramból induljon ki, tapasztalja, hogy becsap a villám, járja végig az ok azonosítási folyamatát, jusson el az okhoz rendelt válaszreakciót realizáló megszakítási rutinhoz, futtassa le a rutint, majd végül kövesse nyomon a főprogramba való visszatérést és legyen tanúja a főprogram felébredésének -továbbfutásának!) | |||||||||||||||||||||||||||
3. Jelölje meg a helyes válaszokat!
![]() | |||||||||||||||||||||||||||
4. Mondja el saját szavaival a context fogalmát és magyarázza meg, miért rendkívül fontos ez a fogalom a megszakítással kapcsolatban! | |||||||||||||||||||||||||||
5. Mondja el saját szavaival egy szubrutin újrahívhatóságának fogalmát, és fogalmazza meg az újrahívhatóság feltételét. (Három társával el is játszhat egy újrahívási szituációt, demonstrálva annak mindkét lehetséges kimenetelét. Szereposztás: Ön a szubrutin (S), egyik társa az A, a másik a B program, a harmadik az operációs rendszer, aki A és B futását vezérli.) | |||||||||||||||||||||||||||
6. Mondja el az I/O port fogalmát, sorolja fel a portok fajtáit és ismertesse funkcióikat. | |||||||||||||||||||||||||||
7. Sorolja fel az I/O kezelés fajtáit és azok alkalmazási területeit | |||||||||||||||||||||||||||
8. Jelölje meg a helyes állításokat!
![]() |