什麼是EXE檔案?
EXE是二進位制的、可移植可執行 (PE)的檔案,它包含程式的機器程式碼、資源和後設資料。
具體檔案結構如下:
-
檔案頭
描述了該檔案的型別、大小、節段(sections)等資訊。 -
節段
程式碼段(.text):包含實際的機器指令(可執行程式碼)或中間語言IL程式碼。
資料段(.data):儲存靜態資料(如全域性變數和常量)。
資源段(.rsrc):包含應用程式使用的資源,如圖示、選單等。
重定位資訊(.reloc):當程式需要載入到非原始地址時,重定位資訊幫助調整程式碼和資料的位置。 -
匯入表和匯出表
列出該程式所依賴的其他庫(如 DLL),以及使用的具體函式。
AOT和JIT的區別
-
AOT(Ahead of Time):提前編譯。在程式執行前就編譯成機器碼或者中間語言IL,存放到檔案系統中。
-
JIT(Just in Time):即時編譯。將中間語言IL在執行時編譯成機器碼。有點像解釋,但不完全是。
C#的編譯執行方式
(1) 原始碼先被編譯成中間語言IL,放入.exe檔案的程式碼段中(.text段)中。
(2) exe檔案在雙擊執行的時候,呼叫CLR(該clr.dll依賴位於.Net Framework資料夾下,見下圖),它使用即時編譯JIT來將IL動態編譯成機器碼,執行具體操作。
C++的編譯執行方式
原始碼直接透過編譯器編譯得到最後的.exe中的機器碼,雙擊直接執行。(整個從原始碼到exe的過程中實際還有預處理、彙編、連結,因為我主要是側重JIT的差異部分展開對比,所以這些步驟省略沒有提)
為什麼C#要多一個即時編譯JIT的步驟?
-
跨平臺性:C# 預先編譯成 IL 程式碼,然後只需在相應平臺上實現相應的 CLR,就可以跨平臺執行。
-
易於管理:JIT階段需要由CLR管理執行,它提供垃圾回收、異常處理、執行緒管理等服務,簡化了開發者的工作。
-
多語言支援:不管語言是什麼,如果都編譯成 IL,CLR就可以統一呼叫(CLR只認識IL)。
什麼又是Mono和IL2CPP?
Mono
-
定義: Mono 是一個開源的跨平臺 .NET 框架的實現,最初由 Xamarin 開發,旨在允許 C# 程式在多種平臺(包括 Windows、Linux 和 macOS)上執行。
-
功能:提供了 CLR 的某些功能,並實現了 C# 編譯器、類庫和執行時。
-
與 CLR 的關係:Mono 實現了 .NET 的一些核心功能,作為一個替代 CLR 的執行時環境,同時支援執行同樣的 IL 程式碼。
IL2CPP
- 定義: IL2CPP(Intermediate Language To C++)是 Unity 引擎原生的一部分,將 C# 中間語言程式碼轉換為 C++ 程式碼,然後編譯成機器碼,適用於各種平臺。
- 功能: 提供更高效的執行時效能和較強的安全性,特別是在移動和遊戲開發中。
- 與 CLR 的關係: IL2CPP 不直接使用 CLR,而是將 IL 轉換為 C++ 程式碼,繞過 CLR 的執行時環境,從而實現更好的效能和跨平臺支援。
兩者的優缺點和現狀
-
(缺)Mono是.Net的一種實現,它會用CLR,也就是會呼叫JIT,但IOS上不支援JIT。
-
(缺)Mono有版許可權制,用不了C#的一些新特性。
-
(缺)Mono雖然跨平臺,但是是需要每個平臺單獨實現了對應CLR,所以有幾個平臺就得寫幾種Mono虛擬機器,比較費事。
-
(優)Mono構建速度快一些(不是指執行),因為JIT是執行時用到什麼才把什麼轉換成機器碼的,CLR中也有一些記憶體管理的方法,會快很多。
-
(優)IL2CPP把IL變成C++,各個平臺本身就是支援C++的。
-
(缺)IL2CPP構建慢一些,因為要提前把所有的程式碼轉換成C++。不過也只是個小問題。
-
(優)IL2CPP執行快,因為最後的機器碼是透過C++得到的。