重學c#系列——c#執行原理(二)

團隊buff工具人發表於2020-07-12

前言

c# 是怎麼執行的呢?是否和java一樣執行在像jvm的虛擬機器上呢?其實差不多,但是更廣泛。

c# 執行環境不僅c#可以執行,符合.net framework 開發規範的都可以執行。

c# 程式在.net framework 上執行,而這個.net framework是windows獨有的,所以這就是為什麼以前c#不跨域的原因,現在c#可以執行在.net core 上,而.net core 跨平臺還跨語言。

無論.net core還是.net framework都包括名為(公共語言執行時(CLR))的虛執行系統和一組統一的類庫。

正文

什麼是CLR

下面是對CLR的介紹:

CLR 是由 Microsoft 執行的公共語言基礎結構 (CLI) 的商業實現,CLI 是作為執行和開發環境(語言和庫在其中無縫協作)建立依據的國際標準。

這樣解釋似乎不夠通俗,那麼它到底幹了啥呢。

舉幾個例子:

(1)類載入器:管理後設資料,載入和在記憶體中佈局類;
(2)Micorsoft 中間語言(MSIL)到原生程式碼編譯器:通過即時編譯把Micorsoft 中間語言轉換為原生程式碼;
(3)程式碼管理器:管理和執行程式碼;
(4)垃圾回收器:為NET.Framework下的所有物件提供自動生命期管理,支援多處理器,可擴充套件;
(5)安全引擎:提供基於證據的安全,基於使用者身份和程式碼來源;
(6)偵錯程式:使開發者能夠除錯應用程式和根據程式碼執行;
(7)型別檢查器:不允許不安全的型別轉換和未初始化變數MSIL可被校驗以保證型別安全。

這樣一看這和java 的虛擬機器非常像啊,這東西難道就是虛擬機器。

下面這種圖,一看就更像了啊:

不管是什麼語言,在.net 平臺上開發,然後轉換成MSIL語言(這裡解釋一下為什麼CLR為什麼叫公共語言執行時,因為只要能編譯成MSIL就能在這上面執行),然後通過CLR執行在windows上。

那麼CLR 是否是像JVM一樣的虛擬機器呢?

CLR是一個支援多種程式語言及多語言互操作,完整的高階虛擬機器。他們做的事情差不多,但是他們的實現原理和執行方式差異巨大。

具體可參考:https://github.com/dotnet/coreclr/blob/master/Documentation/botr/intro-to-clr.md

既然CLR是一個執行公共語言的虛擬機器,執行的還是MSIL語言,那麼這個MSIL語言是怎麼來的呢?這就是微軟貢獻特別大的地方了,微軟向ECMA提供了一份公共語言開發的規範。

下面貼一下概念:

·CLR(公共語言執行庫)是一個CLI的實現,包含了.NET執行引擎和符合CLI的類庫。我們開發的幾乎所有的.NET程式都基於CLR的類庫來實現,並且執行在CLR提供的執行引擎之上。

·CLI(公共語言基礎)是微軟公司向ECMA提交的一份語言和資料格式規範,CLR是目前為止唯一一個公共語言基礎的實現版本。CLI包括了公共型別系統(CTS)、公共中間語言(CIL)、底部檔案格式以及後設資料格式等

·CTS(公共型別系統)定義了一個能夠在CLR上執行的語言規範。儘管有很多語言本身不符合CTS規範,但是通過加強編譯器,改變語言附加規範等手段,使得許多語言能夠編寫出能在CLR上執行的程式。
一種語言編寫的程式編譯能夠在CLR上執行,並不代表這種語言本身完全符合CTS的規範。例如C++語言,仍然保持了其不符合CTS規範的部分,並且在編譯時把這部分不符合CTS的程式碼編譯成原始程式碼而非中間程式碼。

·CLS(公共語言規範)是CTS的一個子集,它定義了希望編寫在.NET平臺上執行的程式的語言所需符合的最小規範。正因為.NET允許由不同語言編寫的程式一起執行,所以才制定出CLS規範,
用以避免不同語言特性產生的錯誤。在.NET Framework中,幾乎所有(但不是所有)的類都是與CLS相容的。在MSDN文件說明中,不相容的類和方法都被特別標記為不相容,例如System名稱空間中的UInt32結構。
UInt32表示32位無符號整數。並不是所有的語言(例如Visual Basic.NET或J#)都支援無符號的資料型別,這種資料型別是與CLS不相容的。

既然是介紹c#,那麼就看下c# 到CLR的執行過程吧。如下圖:

由上圖可以看到只需要修改下面部分,即可實現將原來windows的那一套搬運到不同的平臺上。

現在的.net core就是通過修改這部分來實現跨平臺的,真的是大手筆。以前有一個mono(Mono根據C#和CLR的ECMA標準實現了一份Linux下的CLR,比如說,Linux裡沒有登錄檔的概念,Mono用一個.ini檔案來模擬登錄檔。),

我嘗試使用過,小型網站用用還是可以的(老專案沒有windows主機可以放一下),效率的確低了一些,只是嘗試部署過一次。

.NET Standard

這東西比較關鍵,是一套規範。

官方文件這樣介紹道:

NET Standard 是一套正式的 .NET API 規範,有望在所有 .NET 實現中推出。
推出 .NET Standard 的背後動機是要提高 .NET 生態系統中的一致性。
ECMA 335 繼續為 .NET 實現行為建立統一性,儘管 ECMA 335 指定了一小組標準庫,但 .NET Standard 規範包含範圍更廣的 .NET API。

這東西伴隨著.net core 一起誕生。

這東西出現是解決這樣一個問題的。

現在有.net framewore還有.net core,那麼就有一個問題啊,都是用c#在不同平臺上開發,他們呼叫的api是否一致呢?

比如說有個在.net framework 上有個叫做System.IO.FileSystem的api庫,那麼在.net core上檔案操作是否也叫這個呢?

所以為了統一就制定了一套規範,叫做標準庫,是.net framework和.net core 都有的,有些是.net core上沒有的,比如D3D只有windows作業系統上有,Linux根本就沒有這個東西,所以不會加入標準庫。

同理用標準庫開發的東西是可以在兩套平臺上跑的。

NET Standard 一直在更新,這是歷史原因,那就是當時出來.net core的時候有些api是.net framework 有但是.net core沒有的,這個也不是說是windows都有的api,而是說當時來不及。

NET Standard 2.0 中的新增功能這樣寫道:

.NET Standard 2.0 新增了以下功能:

大幅擴充套件了 API 集

.NET Standard 版本 1.6 中包含了相對較小的一部分 API。 

不包含的 API 許多都是 .NET Framework 或 Xamarin 中的常用 API。

這樣一來,開發變得更為棘手,因為開發人員必須在開發定目標到多個 .NET 實現的應用和庫時,尋找常用 API 的合適替代項。

為了消除此限制,.NET Standard 2.0 向 Standard 舊版本 .NET Standard 1.6 中的可用 API 補充了 20,000 多個 API。 

隨著時間的推移,.net core現在開發就比較輕鬆了。

相關文章