進程、應用程序域、程序集、對象上下文

簡單的說,進程可以承載一組相關的.NET程序集,而應用程序域(簡稱AppDomain)是對該進程的邏輯細分。一個應用程序域進一步被細分成多個上下文邊界,這些邊界用來分組目的相似的.NET對象。使用上下文的概念,CLR便能夠確保恰當地控制那些帶特殊運行時要求的對象。


傳統的進程

用來描述一組資源和程序運行所必需的內存分配。對於每個被加載到內存的可執行程序,在她的生命週期中操作系統會爲之單獨且隔離的進程。由於一個進程的失敗不會影響其他的進程,使用這種方式,運行庫環境將更加穩定。

通過任務管理器,我們可以查看機器上正在運行進程的統計信息:進程的標示符(PID)以及映像名稱。

進程從來不執行任何東西,它只是線程的容器。若要使進程完成某項操作,它必須擁有一個在它的環境中運行的線程,此線程負責執行包含在進程的地址空間中的代碼。
 
線程概述

線程是進程中的基本執行單元(a path of execution)。進程的入口點創建的第一個線程爲主線程。僅僅包含一個主線程的進程是線程安全的。但是,單線程的應用程序用戶響應不好。

開發者使用多線程,有助於改善程序的總體響應。Win32 API可以讓主線程使用如CreateThread()之類的函數,另外產生次線程。每個線程都是進程中的一個獨立執行單元(unique of execution)。比如:一個應用程序可以產生一個工作線程來執行強度大的工作(比如傳輸大文件),當這個次線程正在忙碌的時候,主線程仍然可以對用戶的輸入保持響應。

 

當然,如果單個進程中的線程過多的話,性能反而會下降,因爲CPU需要花不少時間在這些活動線程的來回切換上。另外,單CPU的計算機並沒有能力同一時間運行多個線程。當一個縣城的時間片用完的時候,他會被掛起(suspended),以便執行其他的線程。(找詳細點的資料)


 如果覺得太複雜,那麼只需要記住:線程是Win32進程的獨立執行的單元,每一個進程都有一個主線程,並且每個進程還可以以編程的方式創建額外的線程。更多內容可以參考:關於進程和線程『整理』 、 複習功課:對進程、線程、應用程序域的理解

 

 

.NET平臺下與進程進行交互

   .NET的基類庫可以方便的和進程進行交互。他們位於System.Diagnostics命名空間中,該空間定義了許多的類型,允許我們與系統進程、事件日誌和性能計數器進行交互。

 

 

我們可以看到,與進程打交道的類型有:ProcessProcessModuleProcessModuleCollectionProcessStartInfoProcessThreadProcessThreadCollection

 
詳細的關於Process使用方法可以查閱MSDN,比如獲取/設置進程優先級,獲取進程打開的句柄數。
 

.NET應用程序域
.NET平臺下,程序集並沒有直接加載進進程中(傳統的Win32程序是直接承載的)。.NET可執行程序承載在進程的一個邏輯分區中,術語稱應用程序域(簡稱AppDomain)。一個進程可以擁有多個應用程序域,應用程序域的全部目的就是提供隔離性,相比較與傳統的:
1.應用程序域是.NET平臺操作系統獨立性的關鍵特性。這種邏輯分區將不同操作系統表現加載可執行程序的差異抽象化了。
2.和一個完整的進程相比,應用程序域的CPU和內存佔用要小的多。
3.應用程序域爲承載的應用程序提供了深度的隔離。一個失敗,其他不會失敗。

單個進程可以承載多個應用程序域,每個程序域都和該進程的其他程序域隔離開來,無法相互訪問。在線程啓動的時候,CLR將自動創建這個特定的應用程序域(默認應用程序域)。然後根據需要創建其他程序域。
 
兩邊都有mscorlib.dll,因爲所有關鍵程序集會被CLR自動加載到每一個應用程序域中。
更多內容:C#強化系列文章六:應用程序域(AppDomain)淺析 、寄宿(host)和應用程序域(appdomain)

 
對象上下文
 
應用程序域是承載.NET程序集的進程的邏輯分區。與此相似,應用程序域也可以進一步被劃分爲多個上下文邊界(context boundary)。事實上,.NET上下文爲單獨的應用程序域提供了一種方式,該方式能爲一個給定對象建立“特定的家”(specific home)。
 

使用上下文,CLR可以確保在運行時有特殊需求的對象,可以通過攔截進出上下文的方法調用,得到適當的和一致的處理。這個攔截層允許CLR調整當前的方法調用,以便滿足給定上下文的設定要求。比如,如果定義一個C#類型需要自動線程安全(使用【Synchronization】特性),CLR將會在分配期間創建“上下文同步”。
 

和一個進程定義了默認的應用程序域一樣,每一個應用程序域都有一個默認的上下文(context 0)。大多數.NET對象都會被加載到上下文0中。如果CLR判斷一個新創建的對象有特殊需求,一個新的上下文邊界將會在承載它的應用程序域中被創建。
可以通過Thread.CurrentContext獲得上下文,通過context的ContextProperties屬性獲得描述。

 

Code
// 得到上下文並輸出ID
Context ctx = Thread.CurrentContext;
Console.WriteLine("{0} object in context {1}",
    this.ToString(), ctx.ContextID);
foreach (IContextProperty itfCtxProp in ctx.ContextProperties)
    Console.WriteLine("-> Ctx Prop: {0}", itfCtxProp.Name);
 
1.一個.NET進程可以承載多個應用程序域。每一個應用程序域可以承載多個相關的.NET程序集,並且可以由CLR(或者AppDomain)獨立地加載或卸載應用程序域。
2.一個給定的應用程序域中包含一個或多個上下文。使用上下文,CLR能夠將“由特殊需求的”對象放置到一個邏輯容器中,確保該對象的運行時需求能夠被滿足。
 
程序集
一個.NET應用程序可以由多個程序集拼裝而成的。程序集,簡單來說,就是一個以公共語言運行庫(CLR)爲宿主的、版本化的、自描述的二進制文件。儘管顯示中.NET程序集和以往Win32二進制文件(包括遺留的COM服務對象)的文件擴展名(*.exe或*.dll)完全相同,但是兩者的內部構成幾乎完全不同。
程序集可以促進代碼重用、確定類型邊界、可版本化的單元、自描述的、可配置的。
 

.NET程序集的格式
 

n Win32文件首部
Win32文件首部使程序集可以被Windows系列操作系統加載和操作。使用dumpbin.exe結合/headers標記打開一個.NET程序集,可以瀏覽該程序集的Win32文件首部信息。
 

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 嵌入的數字簽名,使用基於程序集內容的散列值和私鑰值生成。

 

總結

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章