基本信息
CLR(公共語言運行庫,Common Language Runtime)和Java虛擬機一樣也是一個運行時環境,是一個可由多種程式語言使用的運行環境。CLR的核心功能包括:記憶體管理、程式集載入、安全性、異常處理和執行緒同步,可由面向CLR的所有語言使用。並保證套用和底層作業系統之間必要的分離。CLR是.NET Framework的主要執行引擎。
為了提高平台的可靠性,以及為了達到面向事務的電子商務套用所要求的穩定性級別,CLR還要負責其他一些任務,比如監視程式的運行。按照.NET的說法,在CLR監視之下運行的程式屬於“託管的”(managed)代碼,而不在CLR之下、直接在裸機上運行的套用或者組件屬於“非託管的”(unmanaged)的代碼。
CLR將監視形形色色的常見編程錯誤,許多年來這些錯誤一直是軟體故障的主要根源,其中包括:訪問數組元素越界,訪問未分配的記憶體空間,由於數據體積過大而導致的記憶體溢出,等等。
然而,這種對受管理代碼的運行監視是有代價的。雖然當前還不可能精確地得到監視程式運行所需要的開銷,但從當前Beta測試版的性能表現來看,正如Microsoft所承認的那樣,我們可以預料由它導致的性能降低程度至少達到10%。當然,如果監視程式運行能夠將穩定性和可用性提高到一個新的檔次,那么,我們是否仍會懷疑這10%的性能降低是一件壞事?
在處理器性能改善方面,摩爾定律已經一再被證明是正確的。既然如此,我們要得到一台性能增加了10%的伺服器要等待多長時間呢。
NET提供的公共語言運行庫是一種多語言執行環境,支持眾多的數據類型和語言特性。他管理著代碼的執行,並使開發過程變得更加簡單。這是一種可操控的執行環境,其功能通過編譯器與其他工具共同展現。
依靠一種以運行時為目標的編譯器開發的代碼叫做可操控代碼。
元數據:為了使運行時環境可以向可操控代碼提供服務,語言編譯器需要產生一種元數據,它將提供在使用語言中的類型、成員、引用的信息。運行時環境使用元數據定位並載入類,在記憶體中展開對象實例,解決方法調用,產生本地代碼,強制執行安全性,並建立運行時環境的邊界。
可操控執行的含義:對象在執行的過程中完全被運行時環境所控制。運行時環境提供以下服務:自動記憶體管理、調試支持、增強的安全性及與非可操控性代碼的互操作性。條件:1、選擇以運行時為目標的語言編譯器,如VB、C#;2、在組件的輸出類型中使用CLR要求的語言特性。
集成能力
跨語言集成的能力:CLR包含了一個豐富的語言特性集,保證了它與各種程式設計語言的兼容性。這一特性集即公用語言規範,稍後將對其進行詳細說明。
記憶體管理
記憶體管理的自動化:在執行過程中管理應用程式的資源是一項單調而困難的工作。它會將你的注意力從你本應解決的問題中引開。而垃圾收集機制完全解決了程式設計師在編程過程中頭痛的問題,跟蹤記憶體的使用,並知道何時將它們釋放。
在面向對象的環境中,每種類型都標識了對你的應用程式有用的某種資源。為了使用這些資源,你需要為類型分配記憶體。在套用中,訪問一種資源要通過以下步驟:
(1)為類型分配記憶體。
(2)初始化記憶體,設定資源的初始狀態並使其可用。
(3)通過訪問該類型的實例成員來訪問資源。
(4)卸下將被清除的資源狀態。
(5)釋放記憶體。
這一看似簡單的過程在實際的編程中是產生錯誤的主要來源之一。更可怕的是:記憶體中的錯誤往往導致不可預見的結果。如果你有過編程的經驗,想想看,有多少次你的程式因為記憶體訪問錯誤而崩潰?特別是計算機存在多根記憶體條時特別容易記憶體報錯當機。建議升級電腦時換掉原來的記憶體,不要採用加記憶體的方式。
CLR要求所有的資源從可操控的堆(註:在此指一種記憶體結構)中分配。當一個進程被初始化後,CLR保留了一個未被分配的地址空間。這一區域叫做可操控堆。在堆中保持了指向下一個將被分配給對象的堆地址的指針(NEXT)。
初始狀態下,該指針是保留地址空間的基地址。一個套用使用新的操作產生對象。此操作首先檢查新對象需要位元組的大小是否會超出保留空間。如果對象大小合適,指向下一個地址的指針將指向堆中的這個對象,該對象的構造器被調用,新的操作返回對象的地址。
當一個套用請求建立一個對象時,地址空間可能不夠大。堆將發現這一點(通過將新對象的大小與NEXT指針相加,並與堆的大小進行比較),這時垃圾收集器就將被調用。在這裡,CLR引入了“代”的概念。代,指堆中對象產生的先後。這樣,垃圾收集器在將發生溢出時回收屬於特定的“代”的對象,而不是回收堆中的所有對象。
(6)即時編譯
在各種語言的編譯器對原始碼進行編譯之後,在CLR環境中產生的是中間代碼(出於兼容性與跨語言集成的考慮),其內容雖然有效,但在轉化為本地代碼之前它本身是不可執行的。這就是JIT編譯器需要完成的工作。
這裡需要說明一個問題:為什麼要即時編譯,而不是一次性的將中間代碼檔案進行編譯?答案很簡單:原因在於效率。在大型的套用中,你很少會用到程式的全部功能,這種邊執行邊編譯的措施比一次性的完全編譯效率更高。
CLR帶有三個不同的JIT編譯器,在Windows平台中,CLR帶有三個不同的JIT編譯器:
(1)預設的編譯器---主編譯器,由它進行數據流分析並輸出經過最佳化的本地代碼,所有的中間代碼指令均可被它處理。
(2)PREJIT,它建立在主JIT編譯器之上。其運行方式更象一個傳統的編譯器:每當一個.NET組件被安裝時它就運行。
(3)ECONOJIT,在並不充分最佳化的前提下,它能夠快速完成IL代碼到本地碼的轉換,編譯速度與運行速度都非常快。
為了配合編譯器的工作,在.NET SDK的安裝路徑下的/bin目錄中有一個負責管理JIT的應用程式:jitman.exe。具體的使用參見在線上幫助。
版本發布
在當前以組件為基礎的系統中,開發人員和用戶對於軟體版本和發布中存在的問題已經十分熟悉了。當我們安裝一個新的套用之後,我們很可能發現原本正常的某個應用程式奇怪的停止了工作。絕大多數開發人員將時間花在了確保所有註冊表入口的一致性,以便激活COM類上。這就是所謂的“DLL地獄”。
.NET平台通過使用集合來解決這一問題。在這裡,“集合”是一個專有名詞,指類型與資源的發布單元,在很大程度上它等同於今天的DLL。正象.NET用元數據描述類型一樣,它也用元數據描述包含類型的集合。
通常說來,集合由四個部分組成:集合的元數據(集合的內部清單)、元數據描述的類型、實現類型的中間語言代碼和一組資源。在一個集合中,以上四個部分並不是都必須存在,但是,集合中必須包含類型或資源,這樣集合才有意義。
在.NET中一個基本的設計方針是使用孤立的組件。一個孤立的集合的含義是指一個集合只能被一個套用所訪問。在一台機器上,它不被多個套用共享,也不會受其它應用程式對系統的更改的影響。“孤立”賦予了開發人員在自己的程式中對代碼的完全控制權。
任何共享代碼都需要被明確地標識。同時,.NET框架也支持共享集合的概念。一個共享集合指在一台機器上被多個套用共享的集合。共享集合需要嚴格地命名規定。
有了.NET,應用程式間的共享代碼是明確定義的。共享集合需要一些額外的規則來避免我們今天遇到的共享衝突問題。共享代碼必須有一個全局唯一的名稱,系統必須提供名稱保護,並在每當引用共享集合時,CLR將對版本信息進行檢查。
彙編指令
51單片機 彙編 指令CLR:
CLR A
//累加器A 被賦零值,此時為邏輯運算指令。
CLR C
//程式狀態暫存器PSW中的CY位狀態清零,此時為位操作指令。