程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> CLR筆記:1.CLR的執行模型

CLR筆記:1.CLR的執行模型

編輯:關於.NET

術語:CLR :Common Language Runtime 公共語言運行期,有多種不同編程語言使用的運行庫

托管模塊:Managed Module,一個標准的MS Window可移植執行體文件(32位PE32或64位PE32+)

IL:Intermediate Language 中間語言,又叫托管代碼(由CLR管理它的執行)

元數據:metadata,一系列特殊的數據表

程序集:Assembly,抽象的

JIT:just-in-time 即時編譯,將IL編譯成本地CPU指令(本地代碼)

FCL:Framework Class Library,Framework 類庫

CTS:Common Type System,通用類型系統,描述了類型的定義及其行為方式

CLI:Common Language Infrastructure,公共語言基礎結構,這是MS提交給ECMA的一個標准,由CTS 和其他Framwork組件構成

CLS:Common Language Specfication,公共語言規范,詳細規定了一個最小特性集

1.1 將源代碼編譯成托管模塊

CLR編譯過程: C#源碼文件——C#編譯器編譯——托管模塊(IL和元數據)

托管模塊的各個部分:

1.PE32或PE32+頭

標志了文件類型,GUI/CUI/DLL,文件生成時間,在32位還是64位上運行

2.CLR頭

CLR版本,入口方法,模塊元數據,資源,強名稱

3.元數據

3種類型的表

4.IL代碼

元數據包括:

1.描述了模塊中定義的內容,比如類及其成員

2.指出了托管模塊引用的內容,比如導入的類及其成員

3.清單manifest,描述了構成Assembly的文件,由Assembly中的文件實現的公共導出類型,與 Assembly相關聯的資源/數據文件

元數據總是嵌入到與代碼相同的EXE/DLL中,始終與IL保持同步。

元數據用途:

1.消除了對頭/庫文件的依賴,直接從托管模塊中讀取

2.智能感知,從元數據中解析

3.代碼驗證,使用元數據確保代碼只執行安全操作

4.正反序列化

5.垃圾收集器跟蹤對象的生存期以及對象的類型

1.2    將托管模塊合並成程序集

程序集:一個或多個托管模塊/資源文件的邏輯分組,是最小的重用,安全性以及版本控制單元。

既可以生成但文件程序集,也可以生成多文件程序集,這由編譯器工具決定。

CLR是和程序集一起工作的,而不是和托管模塊

1.3    加載CLR

CLRVer命令,查看機器上所有CLR版本

csc的 /plattform開關,決定生成什麼樣的程序集:AnyCPU,x86,x64,Itanium

1.4    執行Assembly代碼

ILAsm命令,將IL編譯成Assembly;ILDasm將Assembly編譯成IL。

高級語言(C#)只是CLR的一個子集,IL則允許訪問CLR的所有功能。

JITCompiler函數,又名JIT編譯器(JITter)

在方法首次執行時,CLR檢測出Main的代碼引用的所有類型,於是CLR分配一個內部數據結構,用於管 理對引用類型的訪問。

在這個內部結構中,每個方法都有一條對應的紀錄以及地址。

對此結構進行初始化時,CLR將每條紀錄都設置為CLR內部包含的一個未文檔化的函數,即 JITCompiler函數。

JITCompiler函數被調用時,找到相應方法的IL,編譯成本地CPU指令,並保存到一個動態內存塊中, 將該內存地址存入內部結構中,最後JITCompiler函數會跳轉到內存塊中的代碼,執行。

第二次執行該方法時,不需要再編譯,直接執行內存塊中的代碼。

JIT將本地代碼保存在動態內存中,一旦程序終止,本地代碼會被丟棄。

csc命令有2個開關會影響代碼的優化:/optimize ,/debug

開關設置 IL代碼質量 JIT本地代碼質量 

/optimize- ,/debug- 未優化 優化 默認設置 

/optimize- ,/debug(+/full/pdbonly) 未優化 未優化 VS2005 Degug狀態 

/optimize+ ,/debug(-/full/pdbonly) 優化 優化 VS2005 Release狀態 

生成未優化的IL時,會在IL中生成NOP指令用於調試,設置斷點。

IL是基於堆棧的。所有指令都是:將操作數壓棧,結果則從棧中彈出

IL有安全驗證機制,保證每一行IL代碼是正確的,不會非法訪問內存,每個托管EXE都在獨自的 AppDomain中運行。

不安全代碼:允許C#直接操作內存字節,在COM互操作時使用,csc以/unsafe開關標記包含不安全代碼 ,其中所有方法都使用unsafe關鍵字。

PEVerify命令檢查程序集所有方法,指出其中的不安全代碼方法。

1.5 本地代碼生成器 NGEN.exe

NGEN.exe將IL預先編譯到硬盤文件中,可以加快程序的啟動速度,減小程序的工作集(所有加載該程序 集的AppDomain不再copy其副本,因為該程序集已經與編譯到文件中,是代碼共享的)。

缺點是:

不能保護IL外洩

生成的文件可能失去同步

因為在文件中要計算首選基地址,而NGEN是靜態計算好的,所以要修改基地址,速度會慢下來

較差的執行性能,NGEN生成的代碼沒有JIT好。

如果不能使用NGEN生成的文件,會自動加載JITCompiler。

1.7    CTS

CTS的一些規定:

1.一個類型可以包含0個或多個成員

2.類型可視化以及類型成員的訪問規則

3.定義了繼承,虛方法,對象生成期的管理規則

4.所有類型最終都從預定義的System.Object繼承

1.8    CLS

如果在C#中定義的類型及其方法,可以在VB中使用,那麼,就不能在C#中定義CLS外的任何 public/protected特性,privated的類型及其成員不受限制。

C#可以有僅大小寫不同的兩個方法——不符合CLS,所以不能是public的。

使用[assembly:CLSComplant(true)]標志程序集,告訴編譯器檢查該程序集的CLS相容性。書上寫得不 明白,我這裡做了一個測試:

using System;


[assembly: CLSCompliant(true)]


namespace ClassLibrary2

{

    public class Class1

    {


        public void A()

        {


        }


        public void a()

        {


        }

    }

}

注意,[assembly:CLSComplant(true)]要寫在namespace外。

我定義了兩個不同方法A和a,編譯器會有警告,說這樣的語法不兼容CLS;如果去掉 [assembly:CLSComplant(true)]聲明,那麼不會有這個警告;如果將a方法改為private,則不會有警告。

中途我使用了ILDasm觀察這個dll,發現兩個方法A和a都存在於IL中,說明IL的語法范圍也大於CLS。

在VB中,我添加了對此dll的引用:

Imports ClassLibrary2
Module Module1Module Module1
    Public Class TClass T
        Public Function A()Function A() As Integer
            Dim c1 As Class1 = New Class1()
        End Function
    End Class
End Module

發現,在c1.後面不會有A或a方法的智能感知,說明VB不能識別不符合CLS的語法。如果修改了dll中的 a方法為private或者刪除a方法,則在VB中可以智能感知到A方法。

可以得出結論,不符合CLS的語法,在另一種語言中是看不到的。

1.9 COM互操作

3種互操作情形:

1.托管代碼可以調用DLL中包含的非托管函數,如Kernal32.dll,User32.dll

2.托管代碼可以使用現成的COM組件

3.非托管代碼可以使用托管類型(C#寫的ActiveX控件或shell擴展)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved