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ó

6.5. Memóriakezelés

6.5. Memóriakezelés

Az Windows NT memóriakezelőjének feladata, hogy a folyamatok virtuális címterének címeit megfeleltesse fizikai címeknek, vagyis elvégezze a logikai-fizikai címtranszformációt. A másik fontos feladata a virtuális memóriakezelés megvalósítása, vagyis a memória terheltsége esetén a régen nem használt memóriaterületeket háttértárra menti, valamint ha hivatkozás történik egy háttértárra mentett memórialapra, a szálat várakoztatja, míg bemozgatja a kérdéses lapot a fizikai memóriába.

Az NT 32 bites virtuális memóriakezelést valósít meg. A memóriát laponként (page) kezeli, foglalás, felszabadítás, háttértárra mentés esetén memórialapokat mozgat.

A fent említett alapszolgáltatáson felül az NT memóriakezelője olyan többletszolgáltatásokat is ad a felhasználóknak, melyek nagyban megnövelik a rendszer hatékonyságát. Ilyen szolgáltatás például a fájlok memóriaként történő elérése (memory mapped files), ami lehetővé teszi a fájlok osztott elérését, vagy a copy-on-write mechanizmus használata, mely lehetőségeket a fejezetben részletesen is ismertetjük.

6.5.1. Memória manager felhasználói interfésze

Az NT memóriakezelőjének szolgáltatásait az alkalmazások a Win32 API interfész függvényeinek meghívásával érhetik el. Az NT memóriakezelője a következő szolgáltatásokat nyújtja a felhasználóknak:

  • virtuális memória allokáció illetve felszabadítás,

  • osztott (shared) memória létrehozása,

  • fájlok osztott memóriához hasonló elérése,

  • virtuális memória kezelése (információkérés, memóriába rögzítése, ki­írá­sa háttértárra stb.),

  • memória védelmi funkciók,

  • kernel színtű funkciók (elsősorban a device driverek) támogatása (például fix fizikai memóriaterület használata).

6.5.2. Memóriafoglalás

A memóriafoglalás két lépésben történik a Windows NT-ben:

  • reserve: virtuális címtartomány lefoglalása.

  • commit: virtuális memória lefoglalása.

A felhasználó természetesen kérheti a két lépés egy függvényhívásban történő végrehajtását. A reserve művelet még nem jelent tényleges memóriafoglalást. A reserve végrehajtásával a folyamat csak deklarálja az operációs rendszer számára, hogy mennyi memóriára lesz, vagy lehet szüksége. A rendszer csak a commit művelet hívásakor foglal tényleges tárterületet a korábban a reserve művelettel már lefoglalt memória részére. Ennek megfelelően csak a commit művelet után tudja a folyamat a memóriát használni, a csak reserved memóriacímre történő hivatkozás hibát okoz.

A memóriafoglalás két lépcsőben történő megvalósításának célja a hatékonyabb működés biztosítása. A reserve hatására az operációs rendszer csak egy belső táblázatában jelzi, hogy a folyamat lefoglalta az adott címtartományt. A rendszer csak a commit hatására fog tényleges memórialapokat (page), illetve ún. backing store-t, a memóriaterület potenciális mentésére szolgáló háttértárat lefoglalni. A kétlépéses memóriafoglalással lehetősége nyílik egy folyamatnak előre lefoglalni egybefüggő címtartományokat úgy, hogy csak a memória tényleges használata esetén – vagyis a commit művelet végrehajtása után – terheli az a rendszer memóriáját.

Jól érzékelhetjük a memóriafoglalás két lépcsőben történő megvalósításának előnyeit például a szálak user stackjének foglalásakor. A stacknek természetesen egy folyamatos címtartománynak kell lennie. Alapértelmezés szerint, ha a szál indításakor másképpen nem kérjük, a rendszer 1 MB memóriát foglal reserve művelettel, de csak 2 lapnyi (x86-os rendszerekben kétszer 4 KB) memóriát foglal commit művelettel. (Az első lap a stack teteje lesz, a második lap pedig arra szolgál, hogy a rendszer érzékelje, ha a stack megtelt, és automatikusan foglaljon commit művelettel új oldalakat.) Ha nem lenne kétlépéses memóriafoglalás, minden szál indulásakor a rendszermemóriából ténylegesen le kellene foglalni 1 MB-nyi területet, melynek valószínűleg jelentős részét a szálak többsége nem is használná. A kétlépcsős memóriafoglalásnak köszönhetően azonban a stack csak akkor terheli a rendszer memóriáját, ha az ténylegesen is használatra kerül.

Meg kell említeni, hogy a memóriafoglalás műveletek mindig lapokat (page) foglalnak, akkor is, ha a folyamat ennél kisebb memóriát kér. (Az x86-os rendszerekben a memórialapok mérete 4 KB.) Ráadásul a reserved (és így természetesen a commited) memórialapok mindig 64 KB-os memóriaegységek határán kezdődnek, ezzel támogatva a memórialapok későbbiekben történő esetleges növelését.

6.5.3. Osztott elérésű memória

Az osztott elérésű memória használata a folyamatok közötti információcsere lehetőségén túl adott esetben jelentősen lecsökkentheti a rendszer memóriaterhelését. Vegyük például azt az esetet, hogy a rendszerben két folyamat is éppen C programot fordít. Az osztott memória használatával lehetséges, hogy a C fordító csak egy példányban kerüljön a memóriába.

A Windows NT az osztott elérésű memóriát (shared memory) illetve a fájlok osztott elérését hasonló módon kezeli. A kezelés alapeleme az ún. section object (szekció objektum). (A section object név helyett a Win32 API file map­ping object elnevezést használ.)

A section object lényege, hogy létrehozásakor hozzátársíthatjuk egy fájlhoz vagy a fájl egy részéhez. Ha a section objecthez társított fájl a rendszer memóriáját a háttértáron reprezentáló ún. page file, a section objecttel osztott memóriát fogunk elérni. A section objectet létrehozása után akár több folyamat is megnyithatja, így biztosított a párhuzamos használata a section object által elért objektumnak, ami tehát lehet memória vagy egy létező fájl is.

Az NT-ben a fájlok mérete, így a section objecten keresztül elért fájlok mérete is lényegesen nagyobb lehet, mint a folyamat memória címtartománya. Ebben az esetben a folyamat nem tudná az egész fájlt elérni. Ennek a problémának a megoldására biztosítja az NT a fájlok egy részének, ún. nézetének (view) a mappelési lehetőségét. A section object létrehozásakor a folyamat definiálhatja, a fájl melyik nézetét, melyik részét szeretné az adott section objecttel elérni.

A fájlok section objecten keresztül történő elérése az NT-ben egy nagyon gyakran alkalmazott művelet. Az alkalmazások így hajtják végre azokat a B/K-műveleteiket, amelyek kimenetét egy fájlba szeretnék irányítani, vagy például így történik a végrehajtható (ún. image) fájlok és a DLL-ek memóriába mappelése is. A cache manager section objectek segítségével éri el az általuk kezelt fájlokat.

6.5.4. Memóriavédelem

A memóriavédelem biztosítja, hogy sem két folyamat, sem egy folyamat és az operációs rendszer ne módosíthassa az egymás címtartományába tartozó memóriaterületeket. (Az osztott elérésű memória természetesen kivétel ez alól.) A kiterjedt memóriavédelem az egyik legfontosabb funkciója az NT-nek, ami miatt megbízhatóan működő, robusztus operációs rendszerként tartják az NT-t számon.

A memóriavédelem négy szinten valósul meg:

  • Az operációs rendszer kernel módban futó komponensei által használt adatstruktúrák a felhasználói módban futó folyamatok számára elérhetetlenek. Bármilyen ilyen elérési kísérlet hardver megszakítást eredményez, és a memóriakezelő egység jelzi a memória elérést kezdeményező szálnak az elérési jog megsértését.

  • Minden folyamat külön virtuális címtartományt használ, melyeknek – eltekintve az osztott elérésű memóriától – nincs közös részük. A folyamatok a memóriát a memóriakezelő egységen keresztül érik el, ami amellett, hogy megfelelő hardver támogatással elvégzi a logikai–fizikai címtranszformációt, biztosítja, hogy egyik folyamat se érjen el egy másik folyamat által használt memórialapot.

  • A fenti, a memóriakezelő címtranszformációja által biztosított implicit memóriavédelmen túl az NT által támogatott processzorok lehetőséget adnak hardver memóriavédelemre. A processzortípustól függően az egyes memóriaterületek különböző védelmi attribútumúak lehetnek (például csak írhatóak, csak olvashatóak, írhatóak és olvashatóak stb.) Az egyes területek elérésekor a memóriakezelő hardver ellenőrzi az elérési jogosultságot. Például a kódszegmensek betöltéskor csak olvasható attribútumot kapnak, így megelőzve a kód átítását.

  • A negyedik védelmi szint az osztott memória elérését biztósító section objectekhez kötődik. A section objectekhez definiálható egy ún. elérési lista (ACL: Access Control List), melyben megadható, hogy mely folyamatok jogosultak az adott section objectet elérni. Ez a módszer teljesen illeszkedik az NT-objektumok védelmi rendszerébe.

6.5.5. Copy-on-Write

A copy-on-write memóriahasználat – mely fordítása talán „írás esetén másolás” lehetne – egy széles körben alkalmazott módszer a használt memória illetve a rendszer memóriakezelő műveleteinek optimalizálására. A copy-on-write jó példája az ún. lusta kiértékelés/végrehajtás (lazy evaluation) elvnek, ami azt mondja, hogy a rendszerben a költséges, vagyis sok erőforrást igénylő műveleteket el kell halasztani mindaddig, amíg azok végrehajtása már ténylegesen kikerülhetetlen nem lesz.

A copy-on-write memóriahasználat működése a következő.

Ha egy folyamat egy írható-olvasható, más folyamatok által is potenciálisan használt section objectet kezd használni, akkor a rendszer nem készít a folyamat számára egy lokális másolatot az egész elért memóriatartalomról annak érdekében, hogy a memória megváltoztatása csak a kérdéses folyamat számára legyen látható. Ehelyett az NT csak bebillenti a memórialapokhoz tartózó copy-on-write (C-o-W) jelzőbitet (flaget) (6.11. ábra).

6.11. ábra. ábra - Copy-on-write memórialapok írást megelőzően

Copy-on-write memórialapok írást megelőzően


Tényleges másolás a rendszerben csak akkor történik, amikor a section object bármelyik használója kezdeményez egy memória írási műveletet. Ekkor a rendszer mielőtt megváltoztatná a memóriatartalmat, a kérdéses memórialapról egy privát másolatot készít az írást kezdeményező folyamat számára (6.12. ábra). Így biztosítja a rendszer „takarékosan”, hogy a változtatás csak az írást kezdeményező folyamat számára legyen látható.

6.12. ábra. ábra - Copy-on-write memórialapok írást megelőzően

Copy-on-write memórialapok írást megelőzően


6.5.6. Memória foglalása

Az NT lapkezelést valósít meg, vagyis a memória allokálása memórialaponként (memory page) történik.

A memóriakezelő kevés szabad fizikai memória esetén háttértárra mentheti az egyes lapokat. Ezt a műveletet nevezzük lapozásnak (paging).

A folyamatok a memórialapokat foglalhatják a rendszer ún.

  • lapozott memória tárából (paged memory pool) és a

  • nem lapozott memória tárából (nonpaged memory pool).

A két memóriatár közötti különbség a lapozásnál van. A nem lapozott memória tárából történt memóriafoglalás esetén a kért memórialapot a rendszer állandóan a fizikai memóriában tartja, sosem menti háttértárra. Ezzel lehet biztosítani, hogy valamilyen szempontból fontos (például driverek által használt) memóriaterületek akkor is a fizikai memóriában maradjanak, ha ritkán használják őket.

6.5.7. A memória mérete

A Windows NT 32 bites memóriacímzést valósít meg, ami minden pro­cessz számára 4 GB virtuális címtartományt jelent. Alapesetben a 4 GB felső 2 GB-os részét használhatják az alkalmazások (00000000-7FFFFFFF címek), míg az alsó 2 GB (80000000-FFFFFFFF) az operációs rendszert tartalmazza. A Windows NT Server Enterprise Edition lehetőséget ad egy boo­to­lás­kor megadható paraméter használatával a user címtartomány 3 GB-ra tör­té­nő növelésére.

A user, illetve a rendszer címtartomány felosztását, valamint a címtartományban a különböző memóriaterületek elosztását a 6.13. ábra mutatja.

6.13. ábra. ábra - A logikai címtér felépítése

A logikai címtér felépítése


Az NT memóriakezelőjének működése – például rendszer általa használt adatmezők méretének változtatásával, vagy a folyamatoknak biztosított memóriaterületek nagyságának módosításával – alkalmazkodik az adott számítógépében lévő fizikai memória méretéhez. Az NT három memória méretkategóriát különböztet meg:

  • kicsi (small),

  • közepes (medium),

  • nagy (large).

A különböző kategóriákhoz tartozó memórianagyságot a 6.14. ábrán láthatjuk. (A memóriák árának csökkenése, így az általánosan használt memóriaméret növekedése ezeket a határokat viszonylag gyorsan megváltoztatja.)

6.14. ábra. ábra - A fizikai memória mérete különböző memóriamodellek esetén

A fizikai memória mérete különböző memóriamodellek esetén


6.5.8. Címtranszformáció

A Windows NT kétszintű indexelést használ a virtuális-fizikai címtranszformációhoz, amit mind az x86-os, mind az Alpha processzorok támogatnak.

A virtuális cím felépítése processzorfüggő. A 6.15. ábra mutatja, hogy x86-os processzor esetén hogyan áll össze a lap könyvtár indexből (PDI: Page Directory Index), laptábla indexből (PTI: Page Table Index), illetve a byte indexből (BI: Byte Index) a virtuális cím.

6.15. ábra. ábra - A virtuális cím felépítése

A virtuális cím felépítése


A PDI illetve a PTI kijelöli az elérendő memórialapot, míg a BI a lapon be­lü­li eltolást adja meg.

A címtranszformáció menetét a 6.16. ábra mutatja be.

Minden folyamathoz tartozik egy lap könyvtár (page directory) maximum 1024 bejegyzéssel. Ennek kezdőcíme a folyamat leíróban (KPROCESS) van. A PDI kijelöli, hogy a táblázat melyik bejegyzésében találjuk a címtranszformációhoz használandó laptábla kezdőcímét. A laptábla egy maximum 1024 bejegyzést tartalmazó táblázat, melyből maximum 512 darab lehet egy folyamaton belül, ami egyben az egy rendszerben használható laptáblák maximális száma is.

Ebben a laptáblában a PTI kijelöli, hogy melyik bejegyzés tartalmazza a használandó memórialap kezdőcímét. A memórialapon belül pedig a BI pontosan kijelöli a keresett byte eltolását.

6.16. ábra. ábra - A címtranszformáció menete x86-os processzorok esetén

A címtranszformáció menete x86-os processzorok esetén