1. 程式人生 > 其它 >C#託管模組與程式集

C#託管模組與程式集

  當寫好了C#的原始碼後,C#編譯器會把原始碼編譯成一個託管模組而非最終的機器語言。這個涉及到CLR的相關功能,因為CLR就是為了將不同的語言編寫(例如C#、VB)出來的原始碼可以更好地在不同平臺使用,而不是針對某一種架構CPU進行編譯。編譯器編譯出託管模組後,最終通過JIT編譯器動態實時編譯託管模組中的IL(中間程式碼)程式碼為CPU指令。

  

  回過頭來說託管模組,託管模組主要包含這些資料:元資料、IL中間程式碼、CLR頭、PE32+頭(32位系統為PE32)

  元資料:一種資料表,其中包含著該模組內一些資料。有三種元資料表,分別是定義元資料表、引用元資料表、清單元資料表。定義元資料表的內容為該模組原始碼中定義的類、欄位、方法等資訊,引用元資料表的內容為該模組引用了哪些類、成員等。清單(Manifest)

則是程式集的一個必備要求,託管模組都有元資料,但不一定都有清單資料表。當一個託管模組有了清單之後,它就可以看作是一個程式集。清單當中記錄著該程式集中的其他檔案的名稱,如下圖用ILDasm檢視的一個程式集的清單內容:

  因為我在檔案頭using了很多其他的程式集,所以清單中就會顯示出來我這個程式集引用了那些其他的程式集。除了這些,清單還記錄著一些類似於版本號以及安全資訊的一些內容在末尾。

  IL中間程式碼:編譯器生成的中間程式碼,之後CLR中的JIT編譯器會將其翻譯成最終的CPU指令

  CLR頭:包含使這個模組成為託管模組的資訊,例如一些標誌、託管模組入口方法(Main)的元資料token、以及一些其他不重要資料的位置/大小。CLR頭在託管模組中並不是很重要,資料大小佔比也是非常小。

  PE32+頭:標準的Windows PE檔案頭

  

  託管模組的核心內容主要是前面兩個,即元資料以及IL中間程式碼。這四種資料組成了託管模組,但CLR並不通過託管模組工作,CLR通過程式集進行工作。程式集是一個抽象的概念,它可以看作是一個或多個託管模組的邏輯性分組。程式集除了託管模組,還包括程式集中需要用到的資原始檔,例如jpg等

  

  程式集一般不是exe就是dll,這倆的區別就是,exe是有自己的程式入口的(Main),dll則是功能性比較多,沒有自己的入口。例如在Visual Studio中,一個專案就可以看作是一個程式集。之前提到過託管模組的清單,這裡細說一下多個或者單個模組是如何合併為一個程式集的。首先,程式集是必須有清單元資料表的,因為清單記錄著程式集的版本、語言文化、釋出者等內容,還包括著構成程式集的檔案的描述檔案。

  舉個例子,比如我現在有兩個原始碼檔案在一個專案裡,分別是RUT.cs和FUT.cs,分別定義不同的型別與方法,這兩個原始碼就可以看作是兩個託管模組,字尾是.netmodule(因為編譯器會將原始碼編譯成託管模組)現在要打包把他們合併成一個程式集。RUT裡的東西不常用,而FUT裡的東西常用,所以編譯合併的時候我們就可以把清單元資料放到FUT.netmodule中,這樣這兩個託管模組就有了清單,可以看作是一個程式集。清單中記錄著程式集中所有檔案的資訊,包括不常用的RUT.newmodule。

  還有一些其他的形式,比如將清單元資料放到一個空的託管模組中

  

  或者程式集中只有一個託管模組也是可以的。

  CLR最終將原始碼程式設計生成程式集,然後對程式集進行執行。所以流程大概就是原始碼-託管模組-程式集。

  程式集有很多好處,比如一個公司要對產品開發很多新的功能模組,就可以這些功能模組各自放到單獨的一個程式集中(dll)。這些功能有些常用有些不常用,甚至有些功能甚至可能根本用不到,那麼公司就可以只讓使用者下載使用者能用到的那些功能模組,這樣就可以減少下載量,同時程式的模組化也得到了保證。