Chapter1 CLR的执行模式
1.1將源代碼編譯成托管模塊
一、托管模塊的各個組成部分
1.PE32或PE32+頭,標準的WindowsPE文件頭,如果這個頭使用的是PE32格式,文件只能在32或64位系統上運行,如果頭是PE32+格式只能在64位系統上運行
2.CLR頭
3.元數據,一組數據表,主要包含兩種表:①描述源代碼中定義的類型和成員②描述源代碼引用的類型和成員。
4.IL(中間語言)代碼,編譯器編譯源代碼時生成的代碼,在運行時,CLR將IL編譯成本地CPU指令。
二、元數據多種用途
1.編譯時,元數據消除了對本地C/C++頭和庫文件的需求(在IL代碼文件中,已經包含和引用的類型/成員有關的全部信息,編譯器可以直接從托管模塊讀取元數據)。
2.使用元數據幫你寫代碼————智能感知。
3.CLR的代碼驗證過程使用元數據確保代碼只執行“類型安全”的操作。
4.序列化-反序列化。
5.允許GC跟蹤對象的生存期。
1.2將托管模塊合并成程序集
程序集:一個或多個模塊/資源文件的邏輯性分組,其次,是重用、安全性以及版本控制的最小單元。它可以是一個可執行應用程序、也可以是個DLL
1.3加載公共語言運行時
CLR管理程序集代碼的執行,所以必須安裝.Net Framework
要知道是否安裝.Net Framework,只需檢查%SystemRoot%\System32目錄中的MSCorEE.dll文件是否存在。
.Net Framework SDK提供了一個名為CLRVer.exe的命令執行程序,它能列出已經安裝了的所有CLR版本
/platform開關選項對生成的模塊的影響以及在運行時的影響
1.4執行程序集的代碼
托管程序集同時包含元數據和IL,IL是與CPU無關的機器語言,但比大多數CPU機器語言要高級,還可以創建初始化對象、調用對象上的虛方法以及直接操作數組元素、捕獲異常并拋出。綜上所述可將IL視為一種面向對象的機器語言,IL可有ILAsm.exe的IL匯編器和ILDasm.exe的IL反匯編。 為了執行一個方法,首先必須把它的IL轉換成本地CPU指令,這是CLR的JIT編譯器的職責。
一個方法首次調用時發生的事情
第二次調用時發生的事情
Main函數第二次調用WriteLine時由于已對WriteLine的代碼進行了驗證和編譯,所以會直接執行內存塊中的代碼,完全跳過JITCompiler函數(一旦進程終止,編譯好的代碼將被丟棄)。
還要注意的是,CLR的JIT會對本地代碼進行優化,可能會花費一些時間,但性能更出色
有兩個C#編譯器的開關會影響代碼的優化:/optimize和/debug
| 編譯器開關設置 | C#IL代碼質量 | JIT本地代碼質量 |
| /optimize-/debug-(默認) | 未優化 | 有優化 |
| /optimize-/debug(+/full/pdbonly) | 未優化 | 未優化 |
| /optimize+/debug(-/+/full/pdbonly) | 有優化 | 未優化 |
使用/optimize-在C#編譯器生成的未優化的IL代碼中,將包含許多NOP(no-operation,空操作)指令,如果在調試期間,還可以在控制流程(如for,while,do,if,else,try,catch和finally語句塊)上設置斷點,使代碼更易于調試,相反如果優化IL代碼,則不能在上述流程中調試。 另外只有在指定/debug(+/full/pdbonly)開關的前提下編譯器才會生成Program Database(PDB)文件
在Visual Studio中項目的
Debug(調試)配置對應的是/optimize-和/debug:full開關。
Release(發布)配置對應的是/optimize+和/debug:pdbonly開關
1.4.1 IL和驗證
IL是基于棧的,在編譯IL到本地指令的過程中,CLR會有一個驗證的過程(包括方法正確數量的參數,正確的參數類型,返回值正確的使用,都有返回語句),在托管模塊的元數據中包含了所有方法和類型信息。
1.4.2 不安全的代碼
不安全代碼允許直接操作內存地址,并可操作這些地址處的字節(通常在與非托管代碼進行交互時,或提高對效率極高的算法時才需要這樣做)
C#采用unsafe關鍵字,要求使用/unsafe編譯器開關來編譯
MS提供了一個PEVerify.exe的程序來檢查程序集的所有方法是否采用不安全代碼
1.5 本地代碼生成器:NGen.exe
可以在一個應用程序安裝到用戶計算機上時,將IL代碼編譯成本地代碼,由于代碼在安裝時已經編譯好了,所以CLR的JIT無需編譯IL代碼,提升性能
兩個應用場景:
加快應用程序的啟動速度:運行時不需要花時間來編譯
減小應用程序的工作集
NGen生成的文件存在一下問題:
沒有只是產權保護
NGen生成的文件可能失去同步(并不是一勞永逸很容易失效)
較差的執行時性能
1.6 Framework 類庫
利用這些程序集可以創建一部分應用
1.Webservice
2.WebForm
3.Windows應用程序
4.RIA(Silverlight)
5.Windows控制臺應用程序
6.Windows服務
7.數據庫存儲過程
8.組件庫
1.7 通用類型系統(CTS)
基本成員
Field、Method、Property、Event
成員訪問修飾符(C#)
private:只能有同一個class類型中的其他成員訪問
protected:可有派生類型訪問,不管那些類型是否在同一個程序集
internal:成員可由同一個程序集的任何代碼訪問
protected internal:成員可有任何程序集中的派生類型訪問,也可由同一程序集的任何類型訪問
public:任何程序集的任何類型訪問
理解“代碼的語言”和“代碼的行為”:
使用不同的語言,用于定義類型的語法也不同,無論使用哪一種語言,類型的行為都是完全一致的,因為最終是由CLR的CTS來定義類型的行為。
eg:CTS規定類型只能單繼承,但C++語言允許多繼承,CTS既不能接受、也不能操作這樣的類型,所以就會報錯。
CTS另一條規則:所有類型必須從預定義的System.Object類型繼承,System.Object類型允許做下面事情:
1.比較兩個實例的相等性
2.獲取實例的哈希碼
3.查詢一個實例的真正類型
4.執行實例的淺拷貝
5.獲取實例對象的當前狀態的一個字符串表示
1.8 公共語言規范(CLS)
CLR集成了所有語言,允許在一種語言中使用由另一種語言創建的對象
C#中特性:[assembly:CLSCompliant(true)]
1.9 與非托管代碼的互操作性
1.托管代碼能調用DLL中的非托管函數
2.托管代碼可以使用現有的COM組件(服務器)
3.非托管代碼可以使用托管類型(服務器)
總結:首先編譯器把源代碼->托管模塊(包含PE32頭、CLR頭、元數據、IL代碼)
由于CLR是不和模塊們一塊工作的,它只愛程序集(assembly)
編譯器不得不把托管模塊們合并成->程序集
于是CLR和程序集在一起了,光在一起不行還是得干活的
CLR有以小弟叫JITCompiler,它對程序集中的IL轉換成本地的CPU指令存到內存中
轉載于:https://www.cnblogs.com/hailiang2013/archive/2013/01/07/2849228.html
總結
以上是生活随笔為你收集整理的Chapter1 CLR的执行模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第三章:Creating Utiliti
- 下一篇: 修改了一下voddown.py