Proces spravovaného spouštění
Spravovaný proces provádění zahrnuje následující kroky, které jsou podrobně popsány dále v tomto tématu:
- Výběr kompilátoru Chcete-li získat výhody poskytované modulem CLR (Common Language Runtime), je nutné použít jeden nebo více kompilátorů jazyka, které se zaměřují na modul runtime.
- Kompilace kódu do zprostředkujícího jazyka Kompilace přeloží zdrojový kód do společného zprostředkujícího jazyka (CIL) a vygeneruje požadovaná metadata.
- Kompilace souboru CIL do nativního kódu V době spuštění kompilátor JIT (just-in-time) přeloží CIL do nativního kódu. Během této kompilace musí kód předat ověřovací proces, který prozkoumá CIL a metadata, aby zjistil, zda je možné kód určit jako bezpečný typ.
- Spuštění kódu Modul CLR (Common Language Runtime) poskytuje infrastrukturu, která umožňuje uskutečnit spuštění a provést služby, které lze použít během spuštění.
Volba kompilátoru
Chcete-li využívat výhod poskytovaných modulem CLR (Common Language Runtime), je nutné použít jeden nebo více kompilátorů jazyka, které se zaměřují na modul runtime, například Visual Basic, C#, Visual C++, F# nebo jeden z mnoha kompilátorů třetích stran, například kompilátor Eiffel, Perl nebo COBOL.
Vzhledem k tomu, že se jedná o vícejazyčné prostředí pro spouštění, podporuje modul runtime širokou škálu datových typů a vlastností jazyka. Použitý kompilátor jazyka určuje, které vlastnosti modulu runtime jsou k dispozici. Pomocí těchto vlastností pak můžete navrhovat vlastní kód. Váš kompilátor, nikoliv modul runtime, stanovuje syntaxi kódu, kterou musí váš kód používat. Pokud musí být komponenta zcela použitelná komponentami napsanými v jiných jazycích, musí exportované typy vaší komponenty vystavit pouze jazykové funkce, které jsou součástí specifikace CLS (Common Language Specification). Můžete použít atribut CLSCompliantAttribute, chcete-li zajistit, aby kód odpovídal specifikaci CLS. Další informace naleznete v tématu Jazyková nezávislost a komponenty nezávislé na jazyce.
Kompilace do CIL
Při kompilaci do spravovaného kódu kompilátor přeloží zdrojový kód do společného zprostředkujícího jazyka (CIL), což je sada instrukcí nezávislá na procesoru, která se dá efektivně převést na nativní kód. CIL obsahuje pokyny pro načítání, ukládání, inicializaci a volání metod u objektů a také pokyny pro aritmetické a logické operace, tok řízení, přímý přístup k paměti, zpracování výjimek a další operace. Před spuštěním kódu musí být kód CIL převeden na kód specifický pro procesor, obvykle kompilátorem JIT (just-in-time). Vzhledem k tomu, že modul CLR (Common Language Runtime) poskytuje jeden nebo více kompilátorů JIT pro každou architekturu počítače, které podporuje, může být stejná sada CIL zkompilovaná a spuštěná v jakékoli podporované architektuře.
Když kompilátor vytvoří soubor CIL, vytvoří také metadata. Metadata popisují typy ve vašem kódu, včetně definice každého typu, podpisů členů každého typu, členů, na které odkazuje kód, a dalších dat, která modul runtime používá v době provádění. CIL a metadata jsou obsaženy v přenosném spustitelném souboru (PE), který je založen a který rozšiřuje publikované soubory Microsoft PE a společný formát souboru objektu (COFF) používané historicky pro spustitelný obsah. Tento formát souboru, který umožňuje CIL nebo nativní kód a metadata, umožňuje operačnímu systému rozpoznat image modulu CLR (Common Language Runtime). Přítomnost metadat v souboru společně se souborem CIL umožňuje, aby se váš kód popsal sám, což znamená, že není nutné používat knihovny typů ani jazyk IDL (Interface Definition Language). Modul runtime vyhledává a extrahuje metadata ze souboru podle potřeby v průběhu provádění.
Kompilace CIL do nativního kódu
Než budete moct spustit běžný zprostředkující jazyk (CIL), musí být zkompilován proti modulu CLR (Common Language Runtime) do nativního kódu pro architekturu cílového počítače. .NET nabízí dva způsoby provedení tohoto převodu:
- Kompilátor JIT (just-in-time) .NET.
- Ngen.exe (generátor nativních imagí)
Kompilace kompilátorem JIT
Kompilace JIT převede CIL na nativní kód na vyžádání v době běhu aplikace, když se načte a spustí obsah sestavení. Vzhledem k tomu, že modul CLR (Common Language Runtime) poskytuje kompilátor JIT pro každou podporovanou architekturu procesoru, můžou vývojáři vytvořit sadu sestavení CIL, která můžou být zkompilovaná a spuštěná na různých počítačích s různými architekturami počítačů. Nicméně pokud spravovaný kód volá nativní rozhraní API specifická pro konkrétní platformu nebo knihovnu tříd specifickou pro konkrétní platformu, bude kód spuštěn pouze v daném operačním systému.
Kompilace JIT bere v úvahu možnost, že některý z kódů nemusí být během provádění nikdy volán. Místo použití času a paměti k převodu všech CIL v souboru PE na nativní kód převede CIL podle potřeby a uloží výsledný nativní kód do paměti tak, aby byl přístupný pro následná volání v kontextu tohoto procesu. Zavaděč vytvoří a připojí zástupnou proceduru ke každé metodě v typu, pokud je typ načten a inicializován. Při prvním zavolání metody předá zástupný kód řízení kompilátoru JIT, který převede CIL pro tuto metodu na nativní kód a upraví zástupný znak tak, aby odkazoval přímo na vygenerovaný nativní kód. Proto následné volání metody zkompilované JIT přechází přímo na nativní kód.
Generování kódu v čase instalace pomocí NGen.exe
Vzhledem k tomu, že kompilátor JIT převede soubor CIL sestavení na nativní kód, když jsou volány jednotlivé metody definované v daném sestavení, má negativní vliv na výkon v době běhu. Ve většině případů je snížení výkonu přijatelné. Důležitější je, že kód generovaný kompilátorem JIT je vázán na proces, který kompilaci spustil. Nemůže být sdílen napříč více procesy. Aby bylo možné sdílet generovaný kód mezi několika vyvoláními aplikace nebo mezi několika procesy, které sdílejí stejnou množinu sestavení, podporuje modul CLR (Common Language Runtime) režim předčasné kompilace. Tento režim kompilace předem používá Ngen.exe (Generátor nativních imagí) k převodu sestavení CIL na nativní kód podobně jako kompilátor JIT. Činnost nástroje Ngen.exe se však od kompilátoru JIT liší třemi způsoby:
- Provádí převod z CIL na nativní kód před spuštěním aplikace místo spuštění aplikace v době, kdy je aplikace spuštěná.
- Kompiluje namísto jedné metody v dané chvíli celé sestavení najednou.
- Uchovává generovaný kód v mezipaměti pro nativní bitové kopie jako soubor na disku.
Ověření kódu
V rámci kompilace do nativního kódu musí kód CIL předat ověřovací proces, pokud správce nenastavil zásady zabezpečení, které kódu umožňují obejít ověření. Ověření prozkoumá CIL a metadata a zjistí, jestli je kód bezpečný, což znamená, že přistupuje pouze k umístěním paměti, ke kterým má oprávnění pro přístup. Bezpečnost typů pomáhá izolovat objekty od ostatních objektů a pomáhá je chránit před neúmyslným nebo zákeřným poškozením. Zároveň zajišťuje, aby bezpečnostní omezení kódu byla spolehlivě vynucena.
Modul runtime vychází ze skutečnosti, že následující tvrzení jsou pravdivá pro kód, který je prokazatelně typově bezpečný:
- Odkaz na typ je striktně kompatibilní s odkazovaným typem.
- U objektu jsou vyvolány pouze vhodně definované operace.
- Identity jsou tím, čím dle jejich tvrzení jsou.
Během procesu ověření se kód CIL zkoumá při pokusu o potvrzení, že kód má přístup k umístěním paměti a volání metod pouze prostřednictvím správně definovaných typů. Kód například nemůže povolit polím objektu, aby byla přístupná takovým způsobem, který umožňuje přetečení oblastí paměti. Kromě toho ověření kontroluje kód a zjišťuje, zda byl CIL správně vygenerován, protože nesprávný kód CIL může vést k porušení pravidel bezpečnosti typů. Proces ověřování zkoumá přesně definovanou sadu typově bezpečných kódů a předává pouze typově bezpečný kód. Některé typově bezpečné kódy však nemusí ověření absolvovat úspěšně z důvodu určitých omezení procesu ověřování a některé jazyky pak záměrně neprodukují kód, který je prokazatelně typově bezpečný. Pokud je typově bezpečný kód vyžadován zásadami zabezpečení, avšak není úspěšně ověřen, bude při spuštění kódu vyvolána výjimka.
Spuštění kódu
Modul CLR (Common Language Runtime) poskytuje infrastrukturu, která umožňuje uskutečnit spravované spuštění a služby, jež lze použít během provádění. Před spuštěním metody je nutné, aby byla zkompilována do kódu specifického pro procesor. Každá metoda, pro kterou byl vygenerován CIL, je JIT-zkompilována při prvním zavolání a pak spusťte. Jakmile příště metodu spustíte, spustí se stávající nativní kód zkompilovaný pomocí kompilátoru JIT. Proces kompilace JIT a následné spuštění kódu se opakuje až do dokončení provádění.
Během provádění obdrží spravovaný kód služby, jako je například uvolňování paměti, zabezpečení, spolupráce s nespravovaným kódem, podpora ladění mezi jazyky, vylepšené nasazení a podpora správy verzí.
V systému Microsoft Windows Vista zavaděč operačního systému kontroluje spravované moduly zkoumáním bitu v hlavičce COFF. Nastavený bit označuje spravovaný modul. Pokud zavaděč odhalí spravované moduly, načte soubor mscoree.dll a poté _CorValidateImage
nebo _CorImageUnloading
upozorní zavaděč ve chvíli, kdy jsou bitové kopie spravovaného modulu načteny nebo uvolněny. _CorValidateImage
provede následující akce:
- Zajistí, aby byl kód platným spravovaným kódem.
- Změní vstupní bod v bitové kopii na vstupní bod v modulu runtime.
V 64bitovém systému Windows upraví _CorValidateImage
bitovou kopii uloženou v paměti její transformací z formátu PE32 na formát PE32+.