Felügyelt végrehajtási folyamat

A felügyelt végrehajtási folyamat a következő lépéseket tartalmazza, amelyeket a témakör későbbi részében részletesen ismertetünk:

  1. Fordító kiválasztása. A közös nyelvi futtatókörnyezet által biztosított előnyök eléréséhez egy vagy több olyan nyelvi fordítót kell használnia, amely a futtatókörnyezetet célozza.
  2. A kód fordítása köztes nyelvre. A fordítás lefordítja a forráskódot egy közös köztes nyelvre (CIL), és létrehozza a szükséges metaadatokat.
  3. A CIL fordítása natív kódra. A végrehajtási időben egy igény szerinti (JIT) fordító natív kódra fordítja le a CIL-t. A fordítás során a kódnak át kell adnia egy ellenőrzési folyamatot, amely megvizsgálja a CIL-t és a metaadatokat annak megállapításához, hogy a kód biztonságos-e.
  4. Kód futtatása. A közös nyelvi futtatókörnyezet biztosítja azt az infrastruktúrát, amely lehetővé teszi a végrehajtást és a végrehajtás során használható szolgáltatásokat.

Fordító kiválasztása

A közös nyelvi futtatókörnyezet (CLR) által biztosított előnyök eléréséhez egy vagy több olyan nyelvfordítót kell használnia, amely a futtatókörnyezetet célozza, például Visual Basic, C#, Visual C++, F#, vagy a számos külső fordító, például az Eiffel, a Perl vagy a COBOL fordító egyikét.

Mivel ez egy többnyelvű végrehajtási környezet, a futtatókörnyezet számos adattípust és nyelvi funkciót támogat. A használt nyelvfordító határozza meg, hogy mely futtatókörnyezeti funkciók érhetők el, és ezeket a funkciókat használva tervezheti meg a kódot. A fordító nem a futtatókörnyezet, hanem a kód által használni kívánt szintaxist határozza meg. Ha az összetevőnek teljesen használhatónak kell lennie más nyelveken írt összetevőkkel, az összetevő exportált típusainak csak a Common Language Specification (CLS) által tartalmazott nyelvi funkciókat kell elérhetővé tenni. Az attribútummal CLSCompliantAttribute meggyőződhet arról, hogy a kód CLS-kompatibilis. További információ: A nyelv függetlensége és a nyelvfüggetlen összetevők.

Fordítás a CIL-be

A felügyelt kód összeállításakor a fordító lefordítja a forráskódot egy közös köztes nyelvre (CIL), amely egy processzorfüggetlen utasításkészlet, amely hatékonyan konvertálható natív kódmá. A CIL utasításokat tartalmaz az objektumok betöltési, tárolási, inicializálási és hívási módszereire, valamint az aritmetikai és logikai műveletekre, a vezérlési folyamatokra, a közvetlen memória-hozzáférésre, a kivételkezelésre és más műveletekre vonatkozó utasításokat. A kód futtatása előtt a CIL-t cpu-specifikus kódmá kell konvertálni, általában egy igény szerinti (JIT) fordítóval. Mivel a közös nyelvi futtatókörnyezet egy vagy több JIT-fordítót biztosít minden támogatott számítógéparchitektúrához, ugyanez a CIL-készlet jiT-fordítással és bármilyen támogatott architektúrán futtatható.

Amikor egy fordító létrehozza a CIL-t, metaadatokat is létrehoz. A metaadatok a kód típusait ismertetik, beleértve az egyes típusok definícióját, az egyes típusok tagjainak aláírását, a kód által hivatkozott tagokat és az egyéb adatokat, amelyeket a futtatókörnyezet a végrehajtáskor használ. A CIL és a metaadatok egy hordozható végrehajtható (PE) fájlban találhatók, amely alapul, és amely kiterjeszti a korábban végrehajtható tartalomhoz használt Microsoft PE és common object file format (COFF) formátumot. Ez a fájlformátum, amely CIL-t vagy natív kódot, valamint metaadatokat tartalmaz, lehetővé teszi az operációs rendszer számára a gyakori nyelvi futtatókörnyezeti rendszerképek felismerését. A metaadatok jelenléte a fájlban a CIL-vel együtt lehetővé teszi a kód leírását, ami azt jelenti, hogy nincs szükség típuskódtárakra vagy interfészdefiníciós nyelvre (IDL). A futtatókörnyezet szükség szerint megkeresi és kinyeri a metaadatokat a fájlból a végrehajtás során.

CIL fordítása natív kódra

A közös köztes nyelv (CIL) futtatása előtt azt a közös nyelvi futtatókörnyezet alapján kell lefordítani a célgép architektúrájának natív kódjához. A .NET kétféleképpen hajtja végre az átalakítást:

Fordítás a JIT-fordítótól

A JIT-fordítás igény szerint natív kódmá alakítja a CIL-t az alkalmazás futási idején, amikor a rendszer betölti és végrehajtja a szerelvény tartalmát. Mivel a közös nyelvi futtatókörnyezet jiT-fordítót biztosít minden támogatott CPU-architektúra számára, a fejlesztők létrehozhatnak egy CIL-szerelvényeket, amelyek JIT-fordítással és különböző gépi architektúrákkal futtathatók különböző számítógépeken. Ha azonban a felügyelt kód platformspecifikus natív API-kat vagy platformspecifikus osztálytárakat hív meg, az csak ezen az operációs rendszeren fog futni.

A JIT-fordítás figyelembe veszi annak lehetőségét, hogy bizonyos kódokat nem hívhat meg a végrehajtás során. Ahelyett, hogy időt és memóriát használ a PE-fájlban lévő összes CIL natív kódká alakításához, a CIL-t szükség szerint konvertálja a végrehajtás során, és a kapott natív kódot a memóriában tárolja, hogy az elérhető legyen a folyamat kontextusában a későbbi hívásokhoz. A betöltő egy csonkot hoz létre és csatol egy típus minden metódusához, amikor a típus betöltődik és inicializálódik. Amikor első alkalommal hív meg egy metódust, a csonk átadja a vezérlést a JIT-fordítónak, amely a metódus CIL-ját natív kódmá alakítja, és módosítja a csonkot, hogy közvetlenül a létrehozott natív kódra mutasson. Ezért a JIT által lefordított metódus későbbi hívásai közvetlenül a natív kódra kerülnek.

Időalapú kódlétrehozás a NGen.exe használatával

Mivel a JIT-fordító natív kódmá alakítja a szerelvény CIL-jét az adott szerelvényben definiált egyes metódusok meghívásakor, ez hátrányosan befolyásolja a teljesítményt futásidőben. A legtöbb esetben ez a csökkent teljesítmény elfogadható. Ennél is fontosabb, hogy a JIT-fordító által létrehozott kód a fordítást kiváltó folyamathoz van kötve. Nem osztható meg több folyamat között. Annak érdekében, hogy a generált kód megosztható legyen egy alkalmazás több meghívása vagy több olyan folyamat között, amely több összeállítással rendelkezik, a közös nyelvi futtatókörnyezet támogatja az idő előtti fordítási módot. Ez az idő előtti fordítási mód a Ngen.exe (natív képgenerátor) használatával konvertálja a CIL-szerelvényeket natív kódmá, hasonlóan a JIT-fordítóhoz. A Ngen.exe működése azonban három módon különbözik a JIT-fordító működésétől:

  • A CIL-ről natív kódra való konvertálást hajtja végre, mielőtt az alkalmazást futtatja az alkalmazás futtatása helyett.
  • Egyszerre egy teljes szerelvényt állít össze egy metódus helyett.
  • A natív képgyorsítótárban létrehozott kódot a lemezen tárolt fájlként megőrzi.

Kódellenőrzés

A natív kódra való fordítás részeként a CIL-kódnak át kell esnie egy ellenőrzési folyamaton, kivéve, ha a rendszergazda olyan biztonsági szabályzatot hozott létre, amely lehetővé teszi a kód megkerülését. Az ellenőrzés megvizsgálja a CIL-t és a metaadatokat annak megállapításához, hogy a kód biztonságos-e, ami azt jelenti, hogy csak azokhoz a memóriahelyekhez fér hozzá, amelyekhez hozzáférése van. A típusbiztonság segít elkülöníteni az objektumokat egymástól, és segít megvédeni őket a véletlen vagy rosszindulatú sérülésekkel szemben. Emellett biztosítja, hogy a kódra vonatkozó biztonsági korlátozások megbízhatóan kikényszeríthetők.

A futtatókörnyezet arra a tényre támaszkodik, hogy a következő utasítások igazak a biztonságos kódhoz:

  • Egy típusra mutató hivatkozás szigorúan kompatibilis a hivatkozott típussal.
  • Egy objektumon csak a megfelelően definiált műveletek lesznek meghívva.
  • Az identitások azok, amelyekről azt állítják, hogy azok.

Az ellenőrzési folyamat során a rendszer megvizsgálja a CIL-kódot annak ellenőrzésére, hogy a kód csak megfelelően meghatározott típusok használatával tud-e hozzáférni a memóriahelyekhez és a hívási módszerekhez. A kód például nem teszi lehetővé az objektum mezőinek olyan módon való elérését, amely lehetővé teszi a memóriahelyek túlfuttatásához. Emellett az ellenőrzés ellenőrzi a kódot annak megállapításához, hogy a CIL megfelelően lett-e létrehozva, mert a helytelen CIL a típusbiztonsági szabályok megsértéséhez vezethet. Az ellenőrzési folyamat egy jól definiált típusbiztos kódkészletet ad át, és csak a biztonságos típusú kódot adja át. Előfordulhat azonban, hogy néhány típusbiztos kód nem felel meg az ellenőrzésnek az ellenőrzési folyamat bizonyos korlátozásai miatt, és egyes nyelvek a tervezés során nem hoznak létre ellenőrizhetően típusbiztos kódot. Ha a biztonsági szabályzat írja elő a típusbiztos kódot, de a kód nem felel meg az ellenőrzésnek, kivétel történik a kód futtatásakor.

Kód futtatása

A közös nyelvi futtatókörnyezet biztosítja azt az infrastruktúrát, amely lehetővé teszi a felügyelt végrehajtás végrehajtását, valamint a végrehajtás során használható szolgáltatásokat. A metódus futtatása előtt a metódust processzorspecifikus kódra kell lefordítani. Minden olyan metódus, amelyhez a CIL létre lett hozva, JIT-fordítással történik, amikor az első alkalommal meghívják, majd futtatja. A metódus következő futtatásakor a rendszer futtatja a meglévő JIT által lefordított natív kódot. A JIT-fordítás, majd a kód futtatásának folyamata a végrehajtás befejezéséig ismétlődik.

A végrehajtás során a felügyelt kód olyan szolgáltatásokat kap, mint a szemétgyűjtés, a biztonság, a nem felügyelt kódokkal való együttműködés, a nyelvek közötti hibakeresési támogatás, valamint a fokozott üzembe helyezés és verziószámozás támogatása.

A Microsoft Windows Vista rendszerben az operációs rendszer betöltője a COFF fejléc egy részének vizsgálatával ellenőrzi a felügyelt modulokat. A beállított bit egy felügyelt modult jelöl. Ha a betöltő észleli a felügyelt modulokat, betölti mscoree.dll, és _CorValidateImage_CorImageUnloading értesíti a betöltőt a felügyelt modul lemezképeinek betöltésekor és eltávolításakor. _CorValidateImage A következő műveleteket hajtja végre:

  1. Biztosítja, hogy a kód érvényes felügyelt kód legyen.
  2. A rendszerkép belépési pontjának módosítása a futtatókörnyezet egyik belépési pontjához.

64 bites Windows _CorValidateImage rendszeren a memóriában lévő rendszerképet a PE32-ről PE32+ formátumra alakítva módosítja.

Lásd még