Ugrás a tartalomhoz

Operációs rendszerek mérnöki megközelítésben

Benyó Balázs, Fék Márk, Kiss István, Kóczy Annamária, Kondorosi Károly, Mészáros Tamás, Román Gyula, Szeberényi Imre, Sziray József

Panem Kiadó

4. fejezet - 2. Az operációs rendszer mint absztrakt, virtuális gép

4. fejezet - 2. Az operációs rendszer mint absztrakt, virtuális gép

Mint az előző fejezetben megállapítottuk, az operációs rendszer egyik fő feladata, hogy egy kényelmesen kezelhető virtuális gépet jelenítsen meg a felhasználói és a programozói felületen. Ebben a fejezetben ennek a virtuális gépnek a fontosabb jellemzőit tárgyaljuk.

A tárgyalás során először most is szoftvertervezői szemlélettel közelítünk az operációs rendszerhez. Egy szoftverrendszer tervezése során a rendszert három nézetből kell leírni:

  • adatnézetből, azaz fel kell térképezni és le kell írni a szereplőket és kapcsolataikat (objektumok, objektummodell, adatszerkezetek),

  • a műveletek, funkciók oldaláról, azaz meg kell határozni az egyes szereplők által, vagy rajtuk végezhető műveleteket (funkcionális modell),

  • a viselkedés, vagy vezérlés oldaláról, azaz le kell írni a működést, azt, hogy melyik művelet mikor hajtódik végre.

Fő rendező elvünk az „adatnézet” lesz, azaz sorra vesszük a legfontosabb fogalmakat, amelyeket az operációs rendszer megjelenít. Ezek a főszereplők a folyamatok, a tárak, a készülékek és a felhasználók. Természetesen az egyes pontokon belül foglalkozunk a fogalmakhoz kötődő funkciókkal és viselkedéssel is.

A fejezet végén foglalkozunk az operációs rendszerek legfontosabb minőségi jellemzőivel, ezek közül kiemelten a védelem és biztonság kérdésével.

2.1. Folyamatok és szálak

A korábbiakban megmutattuk, hogy a különböző típusú rendszerek (kötegelt, időosztásos, valósidejű stb.) egyaránt a multiprogramozás elvén értek el kielégítő hatékonyságot. A multiprogramozás alkalmazása azt jelentette, hogy a kötegelt feldolgozást végző rendszerekben egyidejűleg több munka végrehajtása van folyamatban, az időosztásos rendszeren egyidejűleg több felhasználó kiszolgálása van folyamatban, a valósidejű rendszerekben pedig egyide­jűleg több külső eseményre reagáló feladat végrehajtása lehet folyamatban.

A feldolgozás egységeinek megnevezése a különböző rendszerekben más és más – például munka (job), feladat (task) –, azonban az operációs rendszer szintjén felmerülő problémák jórészt közösek. A megvalósítás közös problémái vezettek a valamennyi rendszerben egyaránt használható folyamat fogalmának kialakulásához, a szakirodalomban azonban a job, task, process kifejezések gyakran egymás szinonimájaként fordulnak elő. A folyamatmodellel szemben a több processzort tartalmazó, multiprocesszáló rendszerek megjelenése újabb követelményt támasztott, mégpedig azt, hogy a modell legyen használható mind multiprogramozott, mind multiprocesszáló rendszerek esetén.

A folyamat (process) tehát a multiprogramozott operációs rendszerek alapfogalma. A kifejezést azonban a köznyelv is, és más szakterületek is elterjedten használják. Folyamaton általában műveletek meghatározott sorrendben történő végrehajtását értjük. A folyamat tehát elkezdődik és befejeződik, közben pedig minden részművelet végrehajtása csak akkor kezdődhet el, ha az előző részművelet végrehajtása már befejeződött. A folyamat tehát önmagában szekvenciális. A folyamatok azonban haladhatnak egymással időben párhuzamosan. A folyamat kiterjedésének megválasztása elvileg önkényes. A folyamat egy szakasza kiválasztható és önmagában is folyamatként vizsgálható, illetve egymást követő folyamatok egyesíthetők, és egyetlen nagyobb folyamatként vizsgálhatók.

A folyamathoz kötődő további általános fogalom a szál fogalma (például a cselekmény több szálon fut). A műveletek sorrendjét szemléletesen úgy is meghatározhatjuk, hogy egy képzeletbeli fonalra egymás után felfűzzük a műveleteket jelképező gyöngyszemeket. Ezzel a hasonlattal a folyamat egy szálon történő végighaladásnak felel meg.

Az operációs rendszerekkel kapcsolatban a folyamat és a szál kifejezés természetesen szűkebb, konkrétabb értelemben használatos.

Az egyes rendszertípusok természetes feldolgozási egységei (egy job végrehajtása, egy felhasználó kiszolgálása, egy technológiai eseményre való rea­gá­lás) folyamatként vizsgálhatók. Ezen folyamatok közös eleme, hogy mindegyikben programok egymást követő végrehajtása történik. A program betöltése és végrehajtása az operációs rendszer egy tipikus művelete, amelyik valamennyi rendszertípusra jellemző. A program több szempontból is összetartozó feldolgozási egység (jól meghatározható funkciója van, többnyire egy fájlban tároljuk, végrehajtáskor egy címtartományt rendelünk hozzá stb.). Egy program végrehajtása az esetek többségében sorrendi, a programon belüli párhuzamosítás speciális esetekben fordul elő. Ezeknek a szempontok­nak az alapján indokolt a különböző típusú rendszerek közös folyamat fogalmát a programok szintjén megragadni.

Az operációs rendszerek körében tehát a folyamat egy program végrehajtása. Pontosabban, a fogalom inkább tárgyiasult értelemben használatos, azaz a folyamat egy végrehajtás alatt álló program. A „végrehajtás alatt álló” úgy értendő, hogy végrehajtása már megkezdődött, de még nem fejeződött be. Így akár multiprogramozott, akár multiprocesszáló a rendszer, egyidejűleg több folyamatot kezel.

Egy program egy végrehajtása egy utasítássorozat végrehajtását jelenti. Ugyanannak a programnak – az adatfüggő elágazások miatt – többféle végrehajtása létezhet. A programkód alapján valamennyi lehetséges végrehajtás előállítható. Felvehetünk egy irányított gráfot, amelynek csomópontjai az utasítások, irányított élei pedig az utasításokat a végrehajtás lehetséges sorrendjében kötik össze (folyamatábra, vezérlési gráf). Egy végrehajtás jellemezhető egy vezérlési szállal, amelyik az irányított gráfon a program belépési pontjától egy befejeződési pontig vezető útnak felel meg.

A fentiek alapján a folyamatról a következő logikai modellt alkothatjuk:

Minden folyamathoz tartozik egy logikai processzor és egy logikai memória. A memória tárolja a programkódot, a konstansokat és a változókat, a programot a processzor hajtja végre. A programkódban szereplő utasítások és a végrehajtó processzor utasításkészlete megfelelnek egymásnak. Egy utasítás végrehajtását – néhány kivételtől eltekintve – oszthatatlannak tekintjük, azaz a folyamat állapotát csak olyan időpontokban vizsgáljuk, amikor egy utasítás már befejeződött, a következő pedig még nem kezdődött meg. A programvégrehajtás egy vezérlési szál mentén, szekvenciálisan történik, alapvetően az utasítások elhelyezkedésének sorrendjében, ettől speciális utasítások esetén van eltérés. A processzornak vannak saját állapotváltozói (programszámláló, veremmutató, regiszterek, jelzőbitek stb.), amelyek értéke befolyásolja a következő utasítás végrehajtásának eredményét.

A memória a RAM-modell szerint működik, azaz

  • tárolórekeszekből áll,

  • egy dimenzióban, rekeszenként címezhető,

  • csak rekeszenként, írás és olvasás műveletekkel érhető el,

  • az írás a teljes rekesztartalmat felülírja az előző tartalomtól független új értékkel,

  • az olvasás nem változtatja meg a rekesz tartalmát, tehát tetszőleges számú, egymást követő olvasás az olvasásokat megelőzően utoljára be­írt értéket adja vissza.

A folyamatot egy adott pillanatban leíró információk (a folyamat állapottere):

  • a memória tartalma, azaz a végrehajtandó programkód, valamint a vál­tozók pillanatnyi értéke,

  • a végrehajtó processzor állapota (programszámláló állása, további regiszterek, jelzőbitek stb. értéke).

Az operációs rendszer feladata, hogy a fizikai eszközökön (fizikai processzor, fizikai memória) egymástól elkülönítetten (védetten) létrehozza és működtesse a folyamatoknak megfelelő logikai processzorokat és memóriákat. A logikai processzor utasításkészlete a fizikai processzor utasításkészleténél egyrészt szűkebb, mivel nem tartalmazza a privilegizált utasításokat, másrészt ugyanakkor bővebb is, mivel az operációs rendszer szolgáltatásait is tartalmazza (lásd be-/kiviteli műveletek stb.). A logikai memória a fizikai tár akár nem összefüggő címtartományára, sőt esetleg háttértár címekre lehet leképezve, ráadásul a leképezés a végrehajtás során esetleg változhat is.

Feltűnhet, hogy ebből a modellből hiányzik a külvilággal tartott kapcsolat eszközrendszere, azaz a be-/kivitel. A tárgyalás ezen szintjén a B/K-műveleteket a logikai processzor utasításkészlete részének tekintjük, hiszen a B/K-műveletekre rendszerhívások állnak rendelkezésre. Valójában a be-/kivitel hatékony szervezése az operációs rendszerek legbonyolultabb funkciói közé tartozik.

A folyamat logikai modellje mind multiprogramozott, mind multiprocesz-szoros rendszerek esetén használható. A multiprogramozott rendszerek jellemzője, hogy egyetlen fizikai processzoron, valamint a hozzá tartozó memórián és perifériákon kell egyidejűleg több folyamatot végrehajtani, azaz több logikai processzort és memóriát működtetni. Ezt úgy is felfoghatjuk, hogy az operációs rendszer a logikai-fizikai leképezés mellett a folyamatok számára erőforrásokat biztosít, azaz erőforrás-kiosztó, illetve gazdálkodási feladatot is ellát.

Multiprocesszoros rendszerek esetén az egyes folyamatoknak megfelelő logikai processzorokat több fizikai processzorra lehet szétosztani. Az erőforrás-gazdálkodás itt több processzorral, valamint a hozzájuk tartozó memóriával való gazdálkodást jelenti. Összefoglalóan:

  • Az operációs rendszerek körében a folyamat egy végrehajtás alatt álló – „életre kelt” – program.

  • A folyamat létrejön (megszületik), amikor a végrehajtás megkezdődik, és megsemmisül (meghal), amikor a végrehajtás befejeződik.

  • A folyamatot egy memória–processzor együttes működésével modellezhetjük, amelynek állapotleírói a memóriatartalom (a végrehajtandó kód és a változók értéke), valamint a processzor állapota (a programszámláló és a regiszterek értéke).

Egyes operációs rendszerek lehetőséget adnak szálak (thread) létrehozására is. A szálak lényegében párhuzamos végrehajtású, közös memóriát használó programrészek a folyamatokon belül (egy program végrehajtása több szálon futhat). A szálaknak saját logikai processzoruk van (a CPU-ért ugyanúgy versenyeznek, mint a folyamatok), azonban memóriáik nincsenek védetten elkülönítve, közös logikai memóriát használnak, azaz a kódon és változókon osztoznak. Emiatt – és ez a szálak alkalmazásának gyakorlati jelentősége – az operációs rendszer lényegesen gyorsabban tud végrehajtani egy átkapcsolást a szálak között, mint a folyamatok között.

A szál és a folyamat megkülönböztetésére használatos a pehelysúlyú (lightweight) és nehézsúlyú (heavyweight) folyamat elnevezés is. A továbbiakban nem teszünk éles különbséget a folyamatok és szálak között, a szálakat általában önálló folyamatoknak tekintjük.