前車之鑒
CLR執行模型這部分已經快被博客園網友講爛了我也就不多講了,下面給出幾個鏈接:
點評:這位哥基本上是從書上完全照搬過來的,沒有任何自己的見解,見此篇文章如見真書。
點評:這篇講得不錯,特別是對.Net的規范和實現,看完他的那兩張圖和下面的說明,你就會明白什么是.Net了。最后說下,這位“菜鳥”哥算得上是一個真正的程序員,廣大的程序猿朋友們應該多向他學習!不過可惜,寫完這一篇,他后面就沒更新了。
點評:女同志寫的,中國教育下的標准版筆記。
A. 什么是.Net
說起.Net估計誰都不陌生,一般我們口中的.net指的是微軟的.net戰略,它包含了規范和實現兩部分。以下這幅圖是根據liudong大哥的圖改寫的。它或許能讓我們更能明白.Net的真正含義。
事實上可以看得出,規范就像一套接口,你想要在那個平台上使用.net就實現該套規范的框架即可。這樣做有什么好處呢?沒錯,就是跨平台,這可是當年微軟鼓吹的一個大亮點,不過后來就只見過在windows平台上有.Net,在后來其他平台上的.Net就全讓Novell公司給做了(目前流行的Iphone上的MonoTouch,Linux和Android上的Mono)。讓你的C#代碼可以在少量修改的情況下運行在不同平台上。事實上,這套規范還有一點好處就是混合編程。利用規范定義好的公共類型系統(CTS)和公共語言規范(CLS)開發出的不同語言的編譯器,生成出來的IL中間語言代碼可以和其他語言生成出的IL中間代碼無縫連接。這是規范的兩大好處。
這里說下混合編程。為什么要使用混合編程呢?混合編程是指一個項目使用了多種語言混合編寫。假設現在有一個造價項目,其中有一塊很復雜的計算使用C#可能會導致效率很低下,這時候使用C++無疑是一個明確的選擇,又或者字符串處理模塊使用perl可能開發效率會更高些,又或者金融計算使用APL語言會更容易實現,所以.Net提供了這樣的功能,讓你的項目可支持多種語言混合起來開發,最后每個模塊生成規范的IL中間語言。但前提是你使用的語言有基於.Net的編譯器。目前支持.Net的語言有:除了常見的C#,C++還有Iron Python、Iron Ruby,Ada,APL,Caml,COBOL,Eiffel,Forth,Fortran,Haskell,Lexico,LISP,LOGO,Lua,Mercury,ML,Mondrian,Oberon,Pascal,Perl,Php,Prolog,RPG,Scheme,Smalltalk 和Tcl/Tk……很遺憾的是,這個特性現在幾乎被我們忽略了。
這也應對了那句話:一流企業賣標准、二流企業賣品牌、三流企業賣產品。不知閣下您的企業是幾流呢?
對於以上涉及到的CLI,CTS,CLS,CIL,CLR,FCL等概念各位看官可以參考這篇文章:
liudong 菜鳥CLR VIA C#之旅(1):品味細節,CLR的執行模型
最后盜用用下菜鳥哥的一幅圖:
下面這幅圖就很好說明各個概念之間的關系。
B. Net程序是如何跑起來的
先看一個圖:
拿個金融項目來說,用C#編寫了整個框架,寫了N多類,新建了N多文件,VB寫了某些界面,也生成了N多文件,Python寫了腳本部分,也生成了N多文件,至於多語言混合編程的好處前面已經講了,那么假設你點了一下‘生成’,系統將會發生什么樣的事情呢?首先將你每個文件生成一個托管模塊(至於托管模塊下面會講)。
由每個托管模塊和你的項目的資源文件例如圖片等,將會一起通過連接器(AL.exe,至於連接器,編譯器更深入的原理請參考大學計算機課程《編譯原理》,這是一門讓你非常蛋疼無比的課)一起‘打包’成最終目標文件dll或者exe(至於生成什么類型,可以在項目屬性頁配置)。這是大概的編譯過程。
C. 什么是托管模塊
托管模塊這個概念,我一開始經常和程序集混在一起。而死人Jeff老濕經常說:“CLR不和托管模塊一起工作,而是和程序集一起工作”。
鄙人認為:托管模塊只是你一個源代碼文件通過對應語言編譯器生成的另外一個更高層封裝的一個文件,里面包含了更多信息(PS:如果你讀過原書,那么里面作者還會手把手教你怎么生成一個后綴為.netmodular托管模塊的哦親)。而程序集是由多個托管模塊和資源文件構成的一個windows可執行體。
好吧,不多說先上一個菜鳥哥哥的圖:
上面那幅圖說的是:一個托管模塊包含了PE32/PE32+頭,CLR頭,元數據,IL代碼。
下面是作者對於這四個概念的敘述:
關於元數據再說明一點,平時我們敲代碼,打個X,可以出個XXXXXO這種智能感應,通過的就是你編譯后的元數據來識別,元數據就相當於以前C++頭文件的升級版,他提取了你源代碼文件中所有的公開屬性,公開方法和接口等。這種做法的方便之處就不多解釋,智能感應只是其中一種。
D. 隱藏章節:IL與反編譯
說起IL,讓我不僅想起了老趙的:
老趙談IL(2):CLR內部有太多太多IL看不到的東西,包括您平時必須了解的那些
老趙談IL(3):IL可以看到的東西,其實大都也可以用C#來發現
對於IL,我就不多講了,講了會被老趙噴的。
其實CLR類似於一個操作系統,只不過它是運行在Windows上,那么CLR也有統一的匯編語言就是IL。而且我們口中的編譯器:就是把你編寫的源代碼,統一轉化成CLR所認識的IL語言,這其實也體現了一個高度封裝的過程。對於這個編譯過程:這其中也發生了很多不為人知的轉化(既然不為人知,那么我也是不知道的),比如去掉注釋,優化代碼。
國際慣例,來個Helloworld:
為了獲得編譯后的IL,我們必須借助一個反編譯神器Reflector,估計地球人都知道(親,如果你還不知道或者苦於找不到破解版,請猛擊這里Reflector7.3帶插件破解版)。
這是它的界面,只要把exe或者dll往里面拖即可,即拖即用。
至於IL代碼,就不多做解釋了,有興趣的童鞋可以查閱相關資料或者看原書作者講解。
private static void Main(string[] args) { Console.WriteLine("Helloworld!"); }
可以看到反編譯出來的結果竟然是沒有了i的定義和賦值。但事實上,在IL代碼中,這部分代碼還是存在的。例如:L-0003:ldc,i4,3 這一句是i的賦值語句,所以千萬別誤會成在生成IL的時候,編譯器自動優化掉了(估計是Reflector反編譯IL代碼時給優化掉了,還望知道的大神講解?)。
這時候估計有些童鞋會說了:啊?幸幸苦苦做出來的軟件,代碼卻被Reflector霸王硬上弓了。要是在根據源代碼重新編寫一個接口一樣,但實現中加入惡意代碼的dll替代原來的dll分發出去,那后面大家都懂的… …。
各種謎團,各種防范技巧,敬請期待下一章:弱命名程序集與強命名程序集。
最后小小說明一下:本系列課程原是我在公司每天下班前的30分鍾培訓內容,所以同時也附上PPT:CLR VIR C#[1]__執行模型。