斗地主你什么时候才会托管?(.NET中的托管于非托管)
文章部分引自《.NET4.0面向?qū)ο缶幊搪?#xff08;基礎(chǔ)篇)》第1章.NET面向?qū)ο缶幊袒A(chǔ)(作者:金旭亮)
?
無意間看到一位四五歲左右小朋友在玩斗地主,總開始到結(jié)束,她一直都在使用“提示”(托管)出牌,你猜的沒錯,到最后她贏了。
那么你什么時候才會使用“托管”呢?“我想繼續(xù)游戲,但是牌太爛了,索性托管吧或者我想玩,但是我會兒剛好有事需要處理”
?
實際上,我們在選擇了.NET Framework平臺后,就該選擇使用什么語言了,但是每種語言都有自己的優(yōu)缺點,例如,在非托管C/C++可對系統(tǒng)(Windows)進行一些很低的控制,可以按照自己的想法管理內(nèi)存,控制線程,當(dāng)然這些事情你如果不想關(guān)心,完全可以丟給CLR去處理,它可以幫你處理的核心功能,比如內(nèi)存管理,程序集加載,安全性,異常處理,線程同步,當(dāng)然這些babyservice的待遇只能給托管的代碼使用。
?
非托管應(yīng)用程序的執(zhí)行過程
首先看一下Windows操作系統(tǒng)執(zhí)行一個普通程序(即非托管程序)的基本過程。
軟件工程師寫的程序,經(jīng)過編譯器轉(zhuǎn)為機器指令后,一般以文件的方式保存在外部存儲器中,當(dāng)CPU執(zhí)行程序時,要先把外部存儲器中的程序指令代碼讀到內(nèi)存。
內(nèi)存被分成很多塊(稱為"內(nèi)存單元"),每個內(nèi)存單元都有一個唯一的地址,指令就存放在以某個特定的地址開始的內(nèi)存區(qū)域(即"若干個內(nèi)存單元的集合")中。保存要執(zhí)行的第一條機器指令的那個內(nèi)存單元就是程序的"入口點(Entry Point)"。
當(dāng)程序執(zhí)行時,CPU從入口點取出第一條指令,開始執(zhí)行,然后再取第二條,依次類推……
把一個程序從外部存儲器上裝入內(nèi)存執(zhí)行是一個復(fù)雜的過程,這個功能由操作系統(tǒng)實現(xiàn),開發(fā)具體應(yīng)用程序的軟件工程師通常不需要手動去寫這部分代碼。
由此可知,程序的運行必須依賴于操作系統(tǒng)(如Windows),而且編譯器生成的程序文件包含的是僅適用于特定CPU架構(gòu)的機器指令,由于不同CPU架構(gòu)的機器指令集不同,所以,這個可執(zhí)行程序無法不加修改地在擁有不同CPU架構(gòu)的計算機上運行。
以這種方式生成的機器指令代碼稱為"非托管代碼(Unmanaged Code)"。非托管代碼不僅不能在不同CPU架構(gòu)的計算機上執(zhí)行,而且通常在不同的操作系統(tǒng)下也不能執(zhí)行,比如一個Windows應(yīng)用程序就無法直接在 Linux下運行,反之亦然,這說明非托管代碼的可移植性是受到較大限制的。
如果需要在擁有不同CPU架構(gòu)的計算機和多種多樣的操作系統(tǒng)上實現(xiàn)同一功能,必須針對每種操作系統(tǒng)和CPU架構(gòu)編寫特定的代碼,這明顯是一種重復(fù)且低效的勞動。
程序能不能只寫一次,到處運行?
完全可以的,這就是 "跨平臺"的設(shè)計思想(Java就是一個典范)。.NET也采用了這種設(shè)計思想,而且走得更遠,.NET在架構(gòu)設(shè)計上不僅允許.NET應(yīng)用程序在各種操作 系統(tǒng)和CPU架構(gòu)上運行,而且允許在同一個程序中混合使用由不同的編程語言開發(fā)出來的軟件組件,.NET的這一特性被稱為"跨語言"。
要支持跨平臺這一特性,軟件工程師編寫的程序經(jīng)過編譯器生成的結(jié)果就不能是依賴于操作系統(tǒng)和特定CPU架構(gòu)的機器指令了,而必須是一種"中立"的、 在各種操作系統(tǒng)和CPU架構(gòu)上都能執(zhí)行的代碼,這種代碼Java稱為"Byte Code(字節(jié)碼)",.NET稱之為"IL(中間語言)"。
但程序最終還是要靠CPU執(zhí)行的,所以,Java的字節(jié)碼和.NET的IL代碼仍然需要最終被翻譯成本地CPU能執(zhí)行的機器指令,這部分功能由一個運行在特定操作系統(tǒng)之上的軟件系統(tǒng)來完成,這個軟件系統(tǒng)被稱之為"虛擬機(Virtual Machine,VM)"。
| ? |
| 圖1-9? 托管代碼運行原理 |
只需為每種操作系統(tǒng)和CPU架構(gòu)提供一個虛擬機,就可以讓同樣一個應(yīng)用程序不加修改地"跑"在運行不同操作系統(tǒng)、擁有不同CPU架構(gòu)的計算機上。
這種運行在虛擬機之上的代碼,被稱為"托管代碼(Managed Code)",其原理如圖1-9所示。
使用C#編譯器csc.exe編譯生成的可執(zhí)行程序?qū)嶋H包含的只是IL指令代碼,這是一種托管代碼,只能運行在.NET虛擬機之上。所以,如果某臺 計算機上沒有安裝.NET Framework,就意味著圖 1 9的"虛擬機"一層不存在,.NET應(yīng)用程序就無法執(zhí)行。對于非Windows的操作系統(tǒng),只要上面有.NET虛擬機,就可以運行.NET程序,通常不需 要修改.NET應(yīng)用程序源代碼再重新編譯。
一個應(yīng)用程序可以只采用托管代碼來構(gòu)建,完全依賴CLR以及.NET Framework類庫,也可以混合使用托管代碼和非托管代碼進行構(gòu)建。托管代碼調(diào)用非托管代碼的技術(shù),在.NET中被稱為"平臺調(diào)用(Platform Invoke)"(見圖1-10)。
| ? |
| (點擊查看大圖)圖1-10? 托管代碼與非托管代碼 |
托管代碼執(zhí)行的過程
.NET下可直接運行的.exe文件包含的是IL指令。IL是微軟和第三方編譯器供應(yīng)商磋商而創(chuàng)建的"虛"機器語言,之所以說它是"虛"的,是說它 獨立于特定架構(gòu)的CPU,并且引入了許多具有面向?qū)ο筇卣鞯闹噶?#xff0c;與傳統(tǒng)的直接面向硬件的匯編指令有著很大的不同,可以看成是"面向?qū)ο蟮?#34;匯編指令。
由于IL指令獨立于特定架構(gòu)的CPU,因此它必須經(jīng)過一個"翻譯"過程,轉(zhuǎn)換成本地CPU支持的機器指令,才可以最終執(zhí)行。這個"翻譯者"就是"JIT編譯器(Just-In-Time Complier)",請看圖1-11。
如圖1-11所示,程序源代碼經(jīng)語言編譯器生成程序集,其中包含IL指令代碼。當(dāng)程序運行時,"類裝載器(Class Loader)"從外部存儲器中將IL指令讀入內(nèi)存,再經(jīng)過JIT編譯器動態(tài)地編譯為本地CPU指令代碼執(zhí)行。在進行即時編譯的過程中,CLR同時檢查這 些IL指令是否違反了一些安全規(guī)則,必要時CLR會停止編譯并中斷程序的執(zhí)行。
| ? |
| (點擊查看大圖)圖1-11? 托管代碼的執(zhí)行過程 |
上述即時編譯和代碼驗證的過程僅僅只是在第一次調(diào)用某個方法時發(fā)生。CLR會將編譯好的本地代碼緩存起來,第二次調(diào)用時就直接調(diào)用緩存中的本地代碼,從而避免了再次編譯所帶來的性能損失。
當(dāng)然這樣的性能損失可以通過升級硬件設(shè)備來減少(避免)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/tymonyang/p/4455508.html
總結(jié)
以上是生活随笔為你收集整理的斗地主你什么时候才会托管?(.NET中的托管于非托管)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 解决时间相减问题
- 下一篇: 【练习5.9】图像掩码、礼帽、cvCop