【CLR via C#】全書提煉總結-第一部分 CLR基礎

概要:

  • CLR的1執行模型
  • 元數據概述
  • 弱命名程序集和強命名程序集
  • 全局程序集緩存GAC
  • CLR定位程序集

CLR的執行模型

IL代碼模型:

基於CLR應用的載入過程:

1. 通過點擊exe或則其它方式觸發Window開始為應用創建進程(Windows會根據EXE的文件頭的信息,來判斷是創建32位or64位進程)

  1. 之後再進程的地址空間中載入MSCorEE.dll,這個MSCoreEE.dll有兩個版本,32位or64位(這個文件被稱之為墊片),32位的位於C:WindowsSystemWoW64,64位的位於C:WindowsSystem32
  2. 然後,MSCorEE.dll會檢測可執行文件使用的CLR的版本信息,根據其版本,載入相應的CLR到進程中。(注意:不同版本的CLR的文件名稱是不一樣的)
  3. 版本1.0 C:WindowsMicrosoft.NETFrameworkv1.0.3705
  4. 版本1.1 C:WindowsMicrosoft.NETFrameworkv1.1.4322
  5. 版本2.0 C:WindowsMicrosoft.NETFrameworkv2.0.50727
  6. 版本4 C:WindowsMicrosoft.NETFrameworkv4.0.30319

注意:其中.NET Framework3.0和3.5 是和 CLR2.0一起發布的,CLR DLL載入是從v2.0.50727中進行載入的

  1. 最後,CLR會載入EXE的程序集到進程中,並找到程序的入口點Main,進而執行相關的代碼

基於CLR的代碼執行過程:

1. 在調用 某個方法時,CLR首相會檢測出該方法引用的所有類型,並為對應的類型分配一個數據結構來管理對類型的引用 2. 在該數據結構內部,所有成員都包含一個記錄項。如果該記錄項是方法,則其包含一個地址,該地址指向該方法的實現。在方法棧的頂端,也就是在方法的入口處,該地址會指向一個未編檔函數,該函數被稱為JITCompiler 3. 如果記錄項中的方法是第一次被執行,則就會調用未編檔函數JITCompiler,在JITCompiler中,首先會在元數據表中查找到該方法的記錄,根據此記錄又可以找到相應的IL代碼,然後CLR會分配一塊內存空間,將IL編譯成本機代碼之後存放在該內存中,並且上述提到的記錄項中的地址由指向JITCompiler改為指向該內存地址 4. 如果記錄項中的方法是第n(n>1)次調用,則會直接通過記錄項中的地址找到本機代碼,不會再經過JITCompiler

元數據概述

託管PE文件由四部分組成: PE32(+)頭、CLR頭、元數據、IL - PE32(+)頭,是Windows要求的標準信息 - CLR頭:是需要CLR支持的特有的模塊,包含CLR的版本信息(major和minor版本號),一些標誌,一個MethodDef token(定義了模塊的入口),可選的強名稱數字簽名.(關於CLR頭的詳細信息可查看CorHdr.h文件) - 元數據:程序集描述文件.由定義表、引用表和清單表構成的二進位數據塊.

- IL:Code

弱命名程序集和強命名程序集

弱命名程序集和強命名程序集的主要區別在於強命名程序集採用了密鑰對對程序集進行簽名.

說明: 這一對密鑰允許對程序集進行唯一標識、保護和版本控制,並且允許將程序集部署到用戶機器的任何地方,甚至是Internet上. 私有部署和全局部署: 私有部署指部署到應用程序的基目錄或子目錄,全局部署指部署到指定目錄中. 強命名程序集有四個重要特性,共同對程序集進行唯一標誌:文件名(不包含擴展名)、版本號、語言文化和公鑰(通常只取公鑰的一部分值) 使用SN.exe對程序集進行簽名:

生成公/私鑰對:SN -k MyCompany.snk

創建含有公鑰的文件: SN -p MyCompany.snk MyCompany.PublicKey sha256 控制檯顯示公鑰:SN tp MyCompany.PublicKey

創建強命名程序集:

csc /keyfile:MyCompany.snk Praogram.cs

VS默認使用的是sha1計算的公鑰,我們在命令行使用的是sha256計算的公鑰,所以上圖看到的公鑰與我們命令行中的不同

這樣,就一致了.

如要在VS中改變計算公鑰的方式.試驗了下書中的方法,在AssemblyInfo.cs中增加如下代碼:

[assembly: AssemblyAlgorithmId(System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA256)]

編譯代碼之後,發現並沒有效果,VS2017仍然使用的是sha1進行的簽名.

此部分正在驗證中....有答案了,過來補充

程序集簽名過程 在對程序集進行簽名時,會對整個PE文件進行hash處理,然後將此hash值用私鑰進行簽名,獲取RSA簽名,並將其存儲在CLR頭中.

同時,公鑰也被嵌入到了PE文件中的AssemblyDef清單元數據表中.

全局程序集緩存GAC

GAC(Global Assembly Cache),全局程序集緩存,將多個應用程序集訪問的程序集放在公認目錄,且CLR在載入的時候會檢查該目錄.

GAC存儲目錄: %SystemRoot%Microsoft.NET/Assembly

將程序集安裝到GAC目錄下最常用的工具:GACUtil.exe、MSI

GACUtil /i GACUtil /u

引用強命名程序集時分兩種,一種是在編譯時引用,一種是在運行時引用:

編譯時,引用的強命名程序集是安裝到編譯器目錄下的程序集. 運行時,引用的強命名程序集是安裝到GAC目錄下的程序集.

注意:

GAC目錄下只能存放強命名程序集,且不能手動放置

CLR定位程序集

推薦閱讀:

查看原文 >>
相關文章