簡單的說,進程可以承載一組相關的.NET程序集,而應用程序域(簡稱AppDomain)是對該進程的邏輯細分。一個應用程序域進一步被細分成多個上下文邊界,這些邊界用來分組目的相似的.NET對象。使用上下文的概念,CLR便能夠確保恰當地控制那些帶特殊運行時要求的對象。
傳統的進程
用來描述一組資源和程序運行所必需的內存分配。對於每個被加載到內存的可執行程序,在她的生命週期中操作系統會爲之單獨且隔離的進程。由於一個進程的失敗不會影響其他的進程,使用這種方式,運行庫環境將更加穩定。
通過任務管理器,我們可以查看機器上正在運行進程的統計信息:進程的標示符(PID)以及映像名稱。
進程從來不執行任何東西,它只是線程的容器。若要使進程完成某項操作,它必須擁有一個在它的環境中運行的線程,此線程負責執行包含在進程的地址空間中的代碼。
線程概述
線程是進程中的基本執行單元(a path of execution)。進程的入口點創建的第一個線程爲主線程。僅僅包含一個主線程的進程是線程安全的。但是,單線程的應用程序用戶響應不好。
開發者使用多線程,有助於改善程序的總體響應。Win32 API可以讓主線程使用如CreateThread()之類的函數,另外產生次線程。每個線程都是進程中的一個獨立執行單元(unique of execution)。比如:一個應用程序可以產生一個工作線程來執行強度大的工作(比如傳輸大文件),當這個次線程正在忙碌的時候,主線程仍然可以對用戶的輸入保持響應。
當然,如果單個進程中的線程過多的話,性能反而會下降,因爲CPU需要花不少時間在這些活動線程的來回切換上。另外,單CPU的計算機並沒有能力同一時間運行多個線程。當一個縣城的時間片用完的時候,他會被掛起(suspended),以便執行其他的線程。(找詳細點的資料)
如果覺得太複雜,那麼只需要記住:線程是Win32進程的獨立執行的單元,每一個進程都有一個主線程,並且每個進程還可以以編程的方式創建額外的線程。更多內容可以參考:關於進程和線程『整理』 、 複習功課:對進程、線程、應用程序域的理解
.NET平臺下與進程進行交互
.NET的基類庫可以方便的和進程進行交互。他們位於System.Diagnostics命名空間中,該空間定義了許多的類型,允許我們與系統進程、事件日誌和性能計數器進行交互。
我們可以看到,與進程打交道的類型有:Process、ProcessModule、ProcessModuleCollection、ProcessStartInfo、ProcessThread、ProcessThreadCollection。
.NET應用程序域
單個進程可以承載多個應用程序域,每個程序域都和該進程的其他程序域隔離開來,無法相互訪問。在線程啓動的時候,CLR將自動創建這個特定的應用程序域(默認應用程序域)。然後根據需要創建其他程序域。
使用上下文,CLR可以確保在運行時有特殊需求的對象,可以通過攔截進出上下文的方法調用,得到適當的和一致的處理。這個攔截層允許CLR調整當前的方法調用,以便滿足給定上下文的設定要求。比如,如果定義一個C#類型需要自動線程安全(使用【Synchronization】特性),CLR將會在分配期間創建“上下文同步”。
和一個進程定義了默認的應用程序域一樣,每一個應用程序域都有一個默認的上下文(context 0)。大多數.NET對象都會被加載到上下文0中。如果CLR判斷一個新創建的對象有特殊需求,一個新的上下文邊界將會在承載它的應用程序域中被創建。
Code
// 得到上下文並輸出ID
Context ctx = Thread.CurrentContext;
Console.WriteLine("{0} object in context {1}",
this.ToString(), ctx.ContextID);
Console.WriteLine("-> Ctx Prop: {0}", itfCtxProp.Name);
.NET程序集的格式
n Win32文件首部
n CLR文件首部
爲了駐留於CLR中,所有的.NET文件都必須還有CLR首部數據塊。它定義了多個標記,它們使得運行庫可以瞭解到託管文件的佈局。例如,文件中元數據和資源的位置、程序集構建的運行庫版本、公鑰值等。使用dumpbin.exe結合/clrheader。
n CIL代碼
程序集的核心部分包含CIL代碼,這些CIL代碼是獨立於平臺和CPU的中間語言。運行時,程序集內部的CIL代碼才被編譯成特定平臺和CPU的指令。
n 類型元數據
元數據完整的描述了程序集內含另行和引用外部類型的格式。
n 程序集清單
詳細記錄了程序集中的每一個模塊,構建程序集的版本以及該程序集引用的所有外部程序集。
n 可選的嵌入資源
單文件程序集和多文件程序集
程序集由多個模塊組成。大多數情況下,程序集只由一個模塊組成。這種情況下,(邏輯)程序集和實際的(物理)二進制文件是一一對應的(因此被稱爲單文件程序集)。多文件程序集市一個.NET*.dll的集合,這些DLL作爲單個邏輯單元進行部署和版本化。通常,其中一個會作爲主模塊,它將包含程序集級別的清單。主模塊的清單記錄了它依賴的每一個*.dll文件
私有程序集
私有程序集要求放置在客戶端應用程序所有在目錄(應用程序目錄)或者子目錄下。
探測過程
.NET運行環境使用一種叫探測(probing)的技術解析私有程序集的位置(這項技術並沒有這個名字聽起來那樣具有侵略性)。
共享程序集
一個共享程序集不在部署使用它的應用程序目錄中,它安裝在GAC。GAC是Windows下名爲Assembly的目錄。
強名稱
在部署程序集到GAC之前,必須賦予它一個強名稱,用於標示給定.NET二進制文件的發行者。它的作用就好比全局唯一標示符(GUID)在COM中的作用。它由一組相關數據組成:
n 程序集的有好名稱(程序集名減去文件擴展名)
n 程序集的版本號(使用[AssemblyVersion]特性賦值)
n 公鑰值(使用[AssemblyKeyFile]特性賦值)
n 用於本地化得可選的區域性標識(使用[AssemblyCulture]特性賦值)
n 嵌入的數字簽名,使用基於程序集內容的散列值和私鑰值生成。
總結