非常感謝某胖達大大的熱心指導,讓我可以真的初步了解這一團玄幻的東西,才有這篇文章的產出~
首先說明一下,這裡要說的是很簡單、對整個 .NET框架運作的初步了解,所以不會有太複雜的內容。
我自己寫C# (.NET)也有一段時間了,每次 coding 完就是按 "Compile(編譯)",沒有Error的話就算完成了這階段的專案了,
對我來說,整個從編譯到產出的檔就是一個黑盒子,我只知道把整個產出的資料夾發佈出去就可以展現我要的結果,
至於過程、產出的檔案完全就一知半解(可能一半還不到),所以昨天特地去請教了大神~~
在描述我的理解最開始,先放一張圖幫助我的說明:(圖片來源:維基百科)
(這是我看過最簡易的.NET運作流程圖了)
1. 先看看最底部,整個過程被分為兩部分:前半段是編譯階段(Compile time),後半段是運行階段(Runtime),而中間碼(Bytecode)銜接兩個階段
2. 我寫的程式(C#),即為「原始碼 Source code」
3. 寫完程式後在VS按下【編譯 Compile】鈕時,「編譯器 Compiler」會將我的原始碼(C# code)編譯成中間碼(Bytecode)
◆ 在解釋編譯是什麼之前,先科普一件事。我寫的程式語言C#是屬於高階語言,簡單來說電腦(執行的機器,更嚴格來說是此機器的系統)是看不懂的,就像不懂日文的我要看日文漫畫一樣,是需要翻譯成中文才能讀懂的,所以從 [C#→電腦能看懂以執行] 這過程中,負責翻譯的機器就叫「編譯器」。編譯,可以簡單理解為一種 "翻譯"。
◆ 在 .NET 的世界裡,並不單單只編譯一次就能讓電腦直接執行,這關係到.NET語言處理器的特性,比較複雜,這裡暫時不談太多。
4. Bytecode (正確翻譯應該是 "字節碼"),是一種中間碼(或稱「中繼語言」)形式,叫做"中間"我猜大概是因為,它是介於原始碼與電腦能執行之間的存在。中間碼也是一種程式語言,在.NET就稱之為Microsoft Intermediate Language(MSIL)
5. 到目前為止,流程已經進行一半了,但其實電腦還是看不懂你的程式@@
6. 電腦看得懂的語言(不管那是什麼阿貓阿狗語言),我們統稱為「原生碼 Native code」。所以要讓電腦看得懂程式,還需再經過一次"翻譯",將中間碼MSIL翻譯成原生碼,而做這件事的就是「CLR」
7. CLR (Common Language Runtime) 本身有內建編譯器(JIT),所以它可以將中間碼MSIL"翻譯"為作業系統的原生碼。(補充:CLR是裝在OS的,基本上是一直啟動,而程式就是在CLR上執行)
8. 但第二次的編譯和第一次的編譯有稍微的不同。請再看上面的流程圖,請注意,CLR已經是在Runtime運行階段了,所以CLR是會在要執行的時候才會將中間碼編譯為作業系統的原生碼,並非像第一次原始碼的編譯一樣先編譯好放著
9. 到產出原生碼這裡,這支程式的演化過程就算告一個段落了~ 接下來就是電腦去反覆的執行、執行、執行....
以上就是我理解後整理出來的@@
我知道完整的整個過程絕對不只這麼簡單,但我這小小的腦袋目前就只能記到這樣QQ
最後來補充幾點:
★ 以上我是以C#為例,.NET可以用很多種語言來寫,像是VB、F#、J#、甚至C++,除了各自的編譯器不同外,流程大致相同,因為各自不同的編譯器會將它們編譯成相同的中間碼MSIL
★ 原生碼的形式有很多,例如DLL, EXE,會依執行的系統而異
★ DLL,是一種library,若給.NET使用,就屬於中間碼;若是給非.NET使用,就會是原生碼。(就是個男女通吃的貨 ((誤
★ CLR因為內建即時編譯器(JIT),有runtime compile的功能(意即一邊執行一邊編譯),所以甚至可以在運行階段(runtime)時動態生DLL,再掛回自己的程式!! 意思是你可以讓程式每次執行不一樣的結果,並且讓這一次執行時產生下一次要執行的DLL!! (這就是個變態…
想了解更多可參考:
◆ 編譯器:http://epaper.gotop.com.tw/pdf/ael010100.pdf
◆ MSIL:http://sun.cis.scu.edu.tw/~nms9115/articles/dotnet/msil/MSIL.pdf
◆ JIT:http://www.telerik.com/blogs/understanding-net-just-in-time-compilation
以上
* 如有錯誤或不足,歡迎指教~~
留言列表