.NET CLR Hosting 簡介
作者:蔡學鏞
某些軟體(例如 Microsoft SQL Server 2005、Borland JBuilder)需要支援 .NET 或 Java,這樣的軟體可以讓 .NET CLR 或 Java VM 寄宿在自己身上,成為自己的一部份,被 CLR/JVM 所寄宿的軟體就稱為 CLR Host(宿主)或 JVM Host。本文章簡單地介紹 .NET CLR Hosting 的觀念。
本文章內容分成三部分,首先介紹 Shim 和 CLR 的關係,接著說明 CLR Host,最後介紹 .NET Framework CLR 2.0 版的 11 個 Hosting Manager。
Shim and VMs
當你執行 Java 程式時,所使用的 java.exe 與 javaw.exe(Windows版),以及當你執行 .NET 程式時,PE 檔 Import Table 內的『mscoree.dll』,其實都不是真正的 VM,它們只是體積很小的一個入口(Portal)程式(mscoree.dll 只有不到 200KB,java.exe 與 javaw.exe 只有不到 50KB),用來將程式導引到真正的 VM 中,這種入口程式被稱為 Shim(填隙物)。不管是 Java 或 .NET,我們都可以透過 Shim 來決定要使用的VM是哪一種 Build Type:Server 或 Client。Server 版的VM針對 Server 類型的程式做最佳化(高產出),Client 版的VM針對 Client 類型的程式做最佳化(高互動)。如果是 .NET,我們甚至可以透過 Shim 來決定要使用 VM 版本號碼(但是這一點 Java 做不到,因為每個版本的 JVM 都有專屬的 Shim,彼此不太相容。)
如果你的系統上安裝了許多套不同版本號碼的 .NET,那麼程式執行時,Shim 會根據預設值或使用者的指定,來決定要使用的版本和 Build Type 為何(請看圖 1)。.NET CLR 的每個版本都附上兩個 Build Type 的 VM,一個是 MsCorWks.DLL(Wks = Workstation),適合用來執行 Client 端的 .NET 程式,另一個是 MsCorSvr.DLL(Svr = Server),適合用來執行 Server 端的 .NET 程式。不管你裝了幾個版本的 .NET Framework,MsCorEE.DLL 只會有一份,放在 C:\Windows\System32 目錄下。而真正的 CLR(VM)是放在 C:\Windows\microsoft.net\framework\v…\ 目錄下的 MsCorWks.DLL 以及 MsCorSvr.DLL。
圖 1
以往 J2SE 同時會附上 Server 和 Client 的 JVM(更早的 JVM 還會多附上 Classic JVM),但是 Java 5.0 以後,J2SE 只附上 Client 的 JVM(jre\bin\client\jvm.dll),沒有附上 Server 的 JVM(jre\bin\server\jvm.dll)。想要具有 Server 的 JVM,必須安裝 J2EE 才行。
Java 程式的執行方式是,先由 OS 載入 Shim 來執行,Shim 會請 OS 動態載入 JVM,然後程式的控制權就交到 JVM 手上,再由 JVM 來載入並執行 Java Bytecode。如圖 2 所示。
圖 2
.NET 程式的執行方式是,先由 OS 直接載入 Managed PE,然後 OS 發現這是 Managed PE,於是立刻載入 Shim 來執行,Shim 會請 OS 動態載入 CLR,然後程式的控制權就交到 CLR 手上,CLR 開始執行 Managed PE 內的 Managed Code。如圖 3 所示。
圖 3
不管是 Java 或 .NET 的方式,都可以改用 Host 程式作為開始,然後再進入整個流程,如圖 4 所示。(但如果是 Java,則圖 4 中的 Shim 必須刪除,而是 Host 之後直接就是 JVM。)
圖 4
CLR Host
某些軟體需要支援 .NET 或 Java,這樣的軟體可以讓 .NET CLR 或 Java VM 寄宿在自己身上,這樣的軟體就稱為 CLR Host(宿主)或 JVM Host(如圖 4 所示)。想要成為 Host,就要使用 Hosting API。微軟的 .NET CLR 的 Hosting API 就稱為 CLR Hosting API,而 Java VM 的 Hosting API 則稱為 Java Invocation API。對於 CLR Hosting API 和 Java Invocation API 來說,兩者比較明顯的差別在於:CLR Hosting 是 COM 介面(但仍有少數幾個獨立的 function),而 Java Native Interface Invocation API 則是 C function 介面。
Microsoft .NET CLR 從 1.0 版就開始支援 CLR Hosting API。為了要支援 SQL Server 2005 的許多功能,在 .NET 2.0 的 CLR 中所支援的 Hosting API 就更完整了。Host 程式就像是在 OS 和 CLR 之間,插入一層,請見圖 5。藉由 .NET 2.0 的 CLR Hosting API,除了不能控制 JIT 之外,你幾乎可以控制 CLR 的一切。從某種角度來看,這也算是一種 API Hook。(但不像 OS API Hook 那麼低階且功能強大。)
圖 5
如何寫出一個 CLR Host 程式?請看下面的四個步驟。
實踐 IHostControl 介面。
你必須設計一個類別,來實踐(implement)IHostControl 介面,如圖 6 所示。此 COM 介面有一個很重要的 function,名為 GetHostManager()。CLR 會呼叫這個 function 來得知你實踐了哪幾個 Hosting Manager,並取得該 Hosting Manager。稍後解釋什麼是 Hosting Manager。
圖 6程式如下:
class MyHostControl : public IHostControl { public: HRESULT __stdcall GetHostManager( REFIID riid, void **ppObject); }; HRESULT __stdcall MyHostControl::GetHostManager( REFIID riid, void **ppObject) { if (riid == IID_IHostMemoryManager) { MyHostMemoryManager *pMemMgr = new MyHostMemoryManager(); *ppObject = (IHostMemoryManager *)pMemMgr; return S_OK; } else if (riid == IID_IHostAssemblyManager) { // 類似上面的作法 } *ppObject = NULL; return E_NOINTERFACE; // 找不到該Manager }
Host Control 的用途只是用來讓 CLR 取得 Manager,一旦 CLR 取得 Manager 之後,Host Control 也就不再有用了。
取得 ICLRRuntimeHost
在 CLR Host 程式中,呼叫 MsCorEE.DLL 內的 CorBindToRuntimeEx(),取得 ICLRRuntimeHost。如下面的程式所示:
實體化一個 Host Control
註冊此 Host Control
利用 ICLRRuntime 介面的 SetHostControl(),來將上面設計好的 MyHostControl 設定進入 CLR 中。程式如下:
CLR Hosting Managers
.NET Framework CLR 2.0 版有 11 個 Hosting Manager。Host Protection Manager 與 Debugging Manager 完全由 CLR 實踐(表 1 中紅色的部分),Thread Pool Manager 完全由 CLR Host 實踐(表 1 中綠色的部分),其他的 Manager 則完全由 CLR 與 Host 兩者共同實現(表 1 中黃色的部分)。由 CLR 所實踐的介面,一律以 ICLR 做為介面名稱的開頭。由 Host 所實踐的介面,一律以 IHost 做為介面名稱的開頭(有一個例外是:IActionOnCLREvent)。表格 1 整理了所有的 Manager 和介面。
表1
CLR Hosting Managers |
Host | CLR |
Assembly Loading Manager |
IHostAssemblyManager IHostAssemblyStore |
ICLRAssemblyReferenceList ICLRAssemblyIdentityManager |
Host Protection Manager |
ICLRHostProtectionManager | |
Failure Policy Manager |
IHostPolicyManager | ICLRPolicyManager |
Memory Manager |
IHostMemoryManager IHostMalloc |
ICLRMemoryNotificationCallback |
Garbage Collection Manager |
IHostGCManager | ICLRGCManager |
Threading Manager |
IHostTaskManager IHostTask |
ICLRTaskManager ICLRTask |
Thread Pool Manager |
IHostThreadPoolManager | |
Synchronization Manager |
IHostSyncManager IHostCriticalSection IHostManualEvent IHostAutoEvent IHostSemaphore |
ICLRSyncManager |
I/O Completion Manager |
IHostIoCompletionManager | ICLRIoCompletionManager |
Debugging Manager |
ICLRDebugManager | |
CLR event Manager |
IActionOnCLREvent | ICLROnEventManager |
大部分的 Manager 都擁有超過一個的介面,每個 Manager 都有一個介面是 Primary Interface(表 1 中採用粗體字者)。所謂的 Primary Interface,是讓系統用來發現 Host 有沒有提供某個 Manager。如果 Manager 完全由 CLR 與 Host 兩者共同實踐,那麼 primary Interface 是在 Host。如果你決定實踐某個管理員,那麼你必須同時實踐該 Manager 全部的介面。
ICLRRuntime 介面有兩個 function,GetCLRControl() 以及 GetHostControl(),可以用來取得 ICLRControl 以及 IHostControl,利用這兩個介面,可以取得許多的 Manager,如圖 7 所示。
圖 7
下面簡單地介紹各種 Hosting Manager 的用途。
Assembly Loading Manager
CLR 有定義一套預定的(default)組件載入機制(圖 x)。有一些特殊的應用需要採用自己的組件載入機制,這時候就可以利用 CLR 的 Assembly Loading Manager,來詳細地控制這一切。
Host Protection Manager
讓 CLR 可以對於 Managed Code 進行某些限制。
Failure Policy Manager
讓 Host可以控制,程式出現錯誤時的處置方式。
Memory Manager
讓 Host 可以提供許多記憶體處理相關的 function(例如:VirtualAlloc()),來取代 Win32 版本的 API。如此一來,Host 可以針對記憶體資源做更詳細的安排。
Garbage Collection Manager
讓 Host 可以強迫 CLR 進行 GC 的動作、取得 GC 的統計資料…等。
Threading Manager
將 Thread 變成 Task,並進行自己的排程(Scheduling)方式。此處所謂的 Task,並不是 process 的意思,而是一種程式的執行單位,可以是 Preemptive 的 Thread(由 OS 負責排程),也可以 Non-Preemptive(Cooperative)的 Fiber(由 Host 自行排程)。
Synchronization Manager
讓 Host 自行提供同步化物件(例如:semaphore、event),而不用 OS 所所提供的同步化物件。
Thread Pool Manager
CLR Host 可以提供自己的 Thread Pool、控制 Thread Pool 內的 Thread 個數。
I/O Completion Manager
對於非同步的(Asynchronous)IO,當動作完成時,就會通知 CLR Host 所提供的 Callback function,讓 CLR Host 可以進一步處理。
Debugging Manager
利用 Debugging Manager,可以控制 debugger 的行為。例如,載入額外的程式資訊檔案。
CLR Event Manager
當 managed code 在執行時,遇到某些特定的事件,就會通知 CLR Host 所提供的 Callback function,讓 CLR Host 可以進一步處理。
利用 CLR Hosting 來支援 .NET 的軟體會越來越多
以前大家會用專屬的技術(特別是 Scripting 語言)來讓自己的軟體系統可以被擴充,以後這樣的狀況勢必會漸漸減少,而是漸漸改用 .NET 的 Managed Code,如此一來,就可以採用各種語言,且功能更完備,耗費的心力更少。這些軟體都需要利用 CLR Hosting 的技術。
隨著 .NET 2.0 的擴充性提高,使用 .NET CLR Hosting 的程式將會越來越多。事實上,目前已經有一些重要的軟體開始運用 CLR Hosting,來讓 managed code 可以在自己的系統中執行,這些軟體包括了 SQL Server 2005、IIS、IE、IBM DB2、AutoDesk AutoCAD。
本文转自cnn23711151CTO博客,原文链接: http://blog.51cto.com/cnn237111/413665,如需转载请自行联系原作者