.NET CLR Hosting 簡介

简介:

.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
圖 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
圖 2

.NET 程式的執行方式是,先由 OS 直接載入 Managed PE,然後 OS 發現這是 Managed PE,於是立刻載入 Shim 來執行,Shim 會請 OS 動態載入 CLR,然後程式的控制權就交到 CLR 手上,CLR 開始執行 Managed PE 內的 Managed Code。如圖 3 所示。

對 3
圖 3

不管是 Java 或 .NET 的方式,都可以改用 Host 程式作為開始,然後再進入整個流程,如圖 4 所示。(但如果是 Java,則圖 4 中的 Shim 必須刪除,而是 Host 之後直接就是 JVM。)

對 4
圖 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
圖 5

如何寫出一個 CLR Host 程式?請看下面的四個步驟。

  1. 實踐 IHostControl 介面。

    你必須設計一個類別,來實踐(implement)IHostControl 介面,如圖 6 所示。此 COM 介面有一個很重要的 function,名為 GetHostManager()。CLR 會呼叫這個 function 來得知你實踐了哪幾個 Hosting Manager,並取得該 Hosting Manager。稍後解釋什麼是 Hosting Manager。

    對 6
    圖 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 也就不再有用了。

  2. 取得 ICLRRuntimeHost

    在 CLR Host 程式中,呼叫 MsCorEE.DLL 內的 CorBindToRuntimeEx(),取得 ICLRRuntimeHost。如下面的程式所示:

    ICLRRuntimeHost *pCLR = NULL;
    HRESULT hr = CorBindToRuntimeEx(
       L"v2.0.40103", //選擇版本為2.0.40103
       L"wks",  // 選擇Build Type為Client
       STARTUP_CONCURRENT_GC, 
       CLSID_CLRRuntimeHost,
       IID_ICLRRuntimeHost,
       (PVOID*) &pCLR;);
  3. 實體化一個 Host Control

    MyHostControl *pHostControl = new MyHostControl();
  4. 註冊此 Host Control

    利用 ICLRRuntime 介面的 SetHostControl(),來將上面設計好的 MyHostControl 設定進入 CLR 中。程式如下:

    pCLR->SetHostControl((IHostControl *)pHostControl);

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
圖 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,如需转载请自行联系原作者




相关文章
|
存储 开发框架 Java
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
在.NET程序开发中,为了将开发人员从繁琐的内存管理中解脱出来,将更多的精力花费在业务逻辑上,CLR提供了自动执行垃圾回收的机制来进行内存管理,开发人员甚至感觉不到这一过程的存在。.NET程序可以找出某个时间点上哪些已分配的内存空间没有被程序使用,并自动释放它们。自动找出并释放不再使用的内存空间机制,就称为垃圾回收机制。本文主要介绍.Net中的GC(垃圾回收)机制及其整体流程。
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
|
.NET 开发框架 前端开发
ASP.NET Core源码学习(一)Hosting
ASP.NET Core源码的学习,我们从Hosting开始, Hosting的GitHub地址为:https://github.com/aspnet/Hosting.git 朋友们可以从以上链接克隆或是下载。
1730 0