沒辦法,這本書寫的太好了,我基本是照抄書的。(*^__^*) 嘻嘻……
我們知道編程人員一般把程式集的載入及反射和寄宿和應用程式定義域結合起來在一起使用。這四種技術一起使用使CLR成為一個功能更加豐富和強大的平台。
.NET Framework運行在Microsoft Windows平台之上,這就意味著.NET
Framework肯定是用Windows可以理解的技術來構建的。首先體現在.NET
Framework中所有的託管模組和組件檔都必須使用Windows的可移植可執行(Portable
Executable,PE)檔案格式,也就是說它們或者必須是Windows EXE檔案,或者必須是一個動態連結程式庫(Dynamic Link
Library,DLL)檔案。
在開發CLR時,Microsoft實際上是將CLR作為一個COM伺服器實現在一個DLL內。也就是說,Microsoft為CLR定義了一個標準的COM介面,並且為該介面和COM伺服器分配了GUID(全球通有標識符)。安裝.NET
Framework時,表示CLR的COM伺服器就像其他COM伺服器一樣被註冊到Windows的註冊表裡了。如果想要瞭解有關這方面的資訊,可以參考和.NET
Framework的SDk一起發布的C++標頭檔MSCorEE.h。該標頭檔中定義了一些GUID和非託管的ICorRuntimeHost介面定義。
任何Windows應用程式都可以寄宿CLR。但是,我們不應該通過調用CoCreateInstance來建立CLR
COM伺服器的執行個體,相反,我們的非託管宿主應該調用CorBindToRuntimeEx函數或者另外一個相似的函數(它們的原型定義在MSCorEE.h檔案中)。CorBindToRuntimeEx函數在MSCorEE.dll檔案(通常位於C:\Windows\System32目錄下)中實現。該DLL被稱為“墊片”(shim),它的職責是判斷建立何種版本的CLR,但它本身不包含CLR
COM伺服器。
一台機器可以安裝多個版本的CLR,但是機器中只有一個版本的MSCorEE.dll檔案(墊片),即機子上最新版本的CLR一起發布的MSCorEE.dll的版本。不過這也有例外,例如在64位版本的Windows,就有兩個版本,一個版本是32位的x86版,另一個是64位的x64或者IA64版(取決於電腦的CPU的架構)。
CLR本身並不在MSCorEE.dll檔案中實現,它在一個稱為MSCorWks.dll檔案中實現。檔案MSCorWks.dll檔案的位置在C:\Windows\Microsoft.Net\Framework\v(版本號碼)。
調用CorBindToRuntimeEx函數時,該函數的參數允許宿主指定它希望建立的CLR的版本,同時還可以指定一些其他設定項。CorBindToRuntimeEx函數除了使用宿主指定的版本資訊,還可以自己搜尋一些額外的資訊(eg.機器安裝了多少個CPU)來決定載入那個版本的CLR——也就是說,墊片不用載入宿主所請求的那個版本的CLR。
預設情況下,當託管可執行檔開始執行時,墊片會查看可執行檔,並提取當初產生好測試應用程式時所使用的CLR的版本資訊。但是,應用程式可以通過在它的XML設定檔中設定requiredRuntime和SupportedRuntime兩個條目來重寫這個預設行為。
CorBindToRuntimeEx函數返回一個指向非託管介面ICLRRuntimeHost的指標。寄宿應用程式可以調用該介面中定義的方法來設定下述各項:
- 設定宿主管理器
告訴CLR宿主希望參與記憶體配置、線程調度或同步、程式集載入等相關的決定。宿主也可以聲明它希望獲得有關垃圾收集啟動和停止以及特定操作逾時的通知。
- 獲得CLR管理器
告訴CLR組織使用某些類或者成員。另外,宿主可以分辨什麼代碼可以調試,什麼代碼不能調試,以及當某個特定事件(例如應用程式定義域的卸載、CLR停止或者堆疊溢位異常等)發生時宿主應調用哪個方法。
- 初始化並啟動CLR。
- 載入程式集並執行程式集中的代碼。
- 停止CLR,從而阻止任何Managed 程式碼在Windows中運行。
有許多原因可以解釋寄宿CLR為何很有用。寄宿允許人呢和應用陳旭支援CLR特徵以及可程式化性,允許應用程式用Managed 程式碼編寫(至少局部可以)。任何寄宿CLR的應用程式都可以為準備擴充應用陳旭的開發人員提供一些便利,這些便利包括以下幾點:
- 可以用任意的程式設計語言編程。
- 代碼被JIT編譯,從而加快速度(與解析相對)。
- 代碼使用垃圾收集,從而避免記憶體泄露和破壞。
- 代碼在安全的“沙箱(sandbox)”中運行。
- 宿主不必擔心提供一個豐富的開發開發環境。宿主可以使用現有的技術,包括:程式設計語言、編譯器、編輯器、調試器、測評器等。
另外,當然,Windows進程完全不必載入CLR,只有需要在進程中執行Managed 程式碼時才載入CLR。一個Windows進程只可以載入一個版本的CLR,因此不可能在一個單獨的進程中載入兩個或者多個版本的CLR。如果一個宿主進程調用了CorBindToRuntimeEx函數多次,那麼每次都會返回同一個ICLRRuntimeHost指標。
一旦CLR載入到Windows的進程,就永遠不會被卸載,即使調用ICLRRuntimeHost介面上的AddRef方法和Release方法也沒有用。要想卸載進程中的CLR,只能終止該進程,導致Windows清理該進程使用的所有資源。