全面分析CLR與操作系統(tǒng)關(guān)系
很久沒有翻譯文章了,不過***眼看到Steven Pratschner的這篇文章時(shí)就覺得很值得我們學(xué)習(xí)。這篇文章在CLR設(shè)計(jì)為我們講述了CLR與操作系統(tǒng)關(guān)系,十分值得一讀。,我會(huì)在稍后繼續(xù)為大家翻譯后邊的部分,希望我的翻譯可以給大家?guī)矸奖恪?/P>
CLR與操作系統(tǒng)關(guān)系概述
過去幾周,我一直在寫一系列文章,來討論創(chuàng)建.Net Compact Framework CLR時(shí)不同的設(shè)計(jì)結(jié)果是如何作出的。在***章中,我討論影響設(shè)計(jì)的環(huán)境因素,并提供CLR內(nèi)存管理的概述。下面幾章我們將詳細(xì)討論JIT編譯器、垃圾回收和類裝入器的主要設(shè)計(jì)思路,還有分析Compact Framework 應(yīng)用程序內(nèi)存使用的信息。貫穿這個(gè)系列,我將著重討論創(chuàng)建Compact Framework CLR時(shí)的設(shè)計(jì)決定,這些設(shè)計(jì)與.Net Framework CLR的設(shè)計(jì)有很大不同。
表面上看起來,.Net Compact Framework是微軟.Net Framework運(yùn)行時(shí)環(huán)境的一個(gè)直接移植。但在設(shè)計(jì)的層次上,這兩個(gè)產(chǎn)品的相似其實(shí)是有意為之,因?yàn)檫@樣會(huì)提供相當(dāng)?shù)暮锰帯ompact Framework和.Net Framework有相同的編程模型,使用相同的文件格式,共享相同的編譯器等等。兩個(gè)編程環(huán)境如此相似的主要好處是,開發(fā)者只要學(xué)習(xí)一個(gè)編程環(huán)境,就可以方便地在另一個(gè)環(huán)境上編程。例如,如果開發(fā)者熟悉.Net Framework,他幾乎不需要花時(shí)間就可以學(xué)會(huì)使用.Net Compact Framework開發(fā)設(shè)備應(yīng)用程序。
無論表面是如何類似,當(dāng)你深入內(nèi)部,你就會(huì)發(fā)現(xiàn)Compact Framework的實(shí)現(xiàn),尤其是CLR組件,與桌面版本的實(shí)現(xiàn)完全不同。無須驚訝,Compact Framework的運(yùn)行環(huán)境直接影響著它內(nèi)部關(guān)鍵組件的架構(gòu)。兩個(gè)主要的環(huán)境因素影響了Compact Framework CLR的設(shè)計(jì),***是CLR需要運(yùn)行在少量的內(nèi)存環(huán)境中,第二是需要方便地跨越處理器和操作系統(tǒng)。這個(gè)系列文章,通過了解對設(shè)計(jì)產(chǎn)生影響的約束條件,來討論CLR的內(nèi)部工作機(jī)制。通過這個(gè)系列我將指出CLR的哪些設(shè)計(jì)做了不同于桌面版本的修改,使托管代碼能夠運(yùn)行在內(nèi)存受限的環(huán)境中。理解CLR的內(nèi)部機(jī)制看起來是一個(gè)深?yuàn)W的話題,但是對于你程序下面的平臺(tái)如何工作有一個(gè)清晰的了解,會(huì)幫助你理解你的應(yīng)用程序是如何使用設(shè)備的資源,也會(huì)幫你判斷內(nèi)存管理或性能相關(guān)的問題。
Compact Framework運(yùn)行在許多不同的操作系統(tǒng)上,但是大部分是安裝在Windows CE上的。讓我們首先來了解一下Windows CE的內(nèi)存機(jī)制。理解操作系統(tǒng)提供給Compact Framework的服務(wù),將幫助我們理解Compact Framework團(tuán)隊(duì)在構(gòu)建CLR時(shí)所作出的決定。The Windows CE Memory Model作為一個(gè)32位操作系統(tǒng),Windows CE可以尋址4GB的虛擬地址空間,這方面和桌面版Windows是一致的。事實(shí)上,內(nèi)存空間的劃分對于Windows CE應(yīng)用程序架構(gòu)是有直接影響的。為了解決Windows CE應(yīng)用程序訪問內(nèi)存的問題,每個(gè)應(yīng)用程序只能操作32MB的虛擬地址空間。內(nèi)存可以被分配到這32MB空間之外,但是這些內(nèi)存是設(shè)備上所有應(yīng)用程序共享的,這些分配的內(nèi)存不是應(yīng)用程序私有的。我們在這里只對Windows CE的內(nèi)存模型進(jìn)行一個(gè)簡單介紹,使我們能夠理解Compact Framework是如何訪問內(nèi)存的。關(guān)于Windows CE內(nèi)存模型更詳細(xì)的描述可以參考Doug Boling的《Programming Windows CE》(中文版名稱《Windows CE程序設(shè)計(jì)》)。
下面的圖描述了Windows CE應(yīng)用程序可用的內(nèi)存區(qū)域。
CLR與操作系統(tǒng)關(guān)系Figure 1
Memory available to Windows CE applications正如我們所看到的,當(dāng)程序運(yùn)行時(shí),會(huì)用到三個(gè)內(nèi)存空間區(qū)域。System Code Space.裝載系統(tǒng)DLL的只讀代碼頁,比如coredll.dll。這是每個(gè)設(shè)備的系統(tǒng)代碼空間,所以所有應(yīng)用程序共享該代碼頁。如果需要,Windows CE可以交換這個(gè)內(nèi)存區(qū)域到存儲(chǔ)設(shè)備以壓縮空間。
Per-Process Address Space.每個(gè)Windows CE進(jìn)程被分配了32MB的虛擬內(nèi)存。每個(gè)線程的棧地址空間、應(yīng)用程序可執(zhí)行文件的代碼頁和任何堆分配和使用的空間都存儲(chǔ)在這個(gè)空間中。
High Memory Area.這1GB的高段內(nèi)存區(qū)域?yàn)榇罅康奶摂M內(nèi)存請求提供了虛擬地址空間。任何對VirtulaAlloc的調(diào)用請求的虛擬內(nèi)存空間將被分配到這部分空間中。另外,所有的內(nèi)存映射文件將被存儲(chǔ)在高段內(nèi)存中。所有存儲(chǔ)在高地址內(nèi)存區(qū)域中的數(shù)據(jù)對設(shè)備上的所有應(yīng)用程序可見。如果需要,Windows CE可以將將高地址內(nèi)存區(qū)域交換分頁到存儲(chǔ)設(shè)備中。
當(dāng)程序運(yùn)行時(shí),.Net Compact Framework從這三個(gè)區(qū)域中獲取需要的內(nèi)存。正如我們所見,為了給托管應(yīng)用程序的開發(fā)者提供***體驗(yàn),Compact Framework管理每個(gè)進(jìn)程的地址空間。.NET Compact Framework Memory Management Basics提高開發(fā)者生產(chǎn)力是促使.Net Framework和.Net Compact Framewok被廣泛采用的主要原因。對于CLR提高開發(fā)者生產(chǎn)力的討論經(jīng)常圍繞著自動(dòng)內(nèi)存管理(垃圾收集)、進(jìn)程獨(dú)立等話題展開。Compact Framework除了明確提供了這些功能外,也提供了更多幫助開發(fā)者提高移動(dòng)設(shè)備程序開發(fā)生產(chǎn)力的更多功能。特別是.Net Compact Framework CLR代替開發(fā)者管理每個(gè)進(jìn)程的32MB虛擬內(nèi)存空間。所以開發(fā)者就不必為他們的程序在32MB空間中分配或釋放內(nèi)存而擔(dān)心了。Compact Framework使編寫內(nèi)存受限設(shè)備上的應(yīng)用程序變得簡單。我們將看到,在這個(gè)系列文章中,許多構(gòu)建.Net Compact Framework CLR的關(guān)鍵設(shè)計(jì)決定就是為了有效地管理每個(gè)進(jìn)程32MB的虛擬內(nèi)存空間。Windows CE將每個(gè)進(jìn)程限制到一個(gè)小的虛擬地址空間中,而Compact Framework團(tuán)隊(duì)所要做的事情就是設(shè)計(jì)一個(gè)平臺(tái),讓應(yīng)用程序在給定的空間中運(yùn)行得更好。
在描述允許在內(nèi)存受限設(shè)備上的設(shè)計(jì)細(xì)節(jié)前,我們需要先來看一下,當(dāng)執(zhí)行一個(gè)托管程序時(shí),操作系統(tǒng)和CLR創(chuàng)建的所有運(yùn)行時(shí)數(shù)據(jù)。在我討論完運(yùn)行一個(gè)程序需要的數(shù)據(jù)種類后,我將告訴大家CLR會(huì)將哪些運(yùn)行時(shí)數(shù)據(jù)分配到Windows CE的哪個(gè)內(nèi)存區(qū)域中去。我們首先來考慮“Hello World”程序運(yùn)行時(shí),運(yùn)行時(shí)數(shù)據(jù)的哪些種類需要內(nèi)存。
- using System;
- using System.ComponentModel;
- using System.Drawing;
- using System.Text;
- using System.Windows.Forms;
- namespace HelloDevice
- {
- public class Form1 : Form
- {
- private MainMenu mainMenu1;
- private Label label1;
- public Form1()
- {
- InitializeComponent();
- }
- private void InitializeComponent()
- {
- this.mainMenu1 = new System.Windows.Forms.MainMenu();
- this.label1 = new System.Windows.Forms.Label();
- // Position the label
- this.label1.Location = new System.Drawing.Point(64, 81);
- this.label1.Size = new System.Drawing.Size(100, 20);
- this.label1.Text = "Hello Device!";
- // Size the form
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(240, 268);
- this.Controls.Add(this.label1);
- thisthis.Menu = this.mainMenu1;
- this.MinimizeBox = false;
- this.Text = "Simple App";
- }
- }
- static class Program
- {
- static void Main()
- {
- Application.Run(new Form1());
- }
- }
- }
正如你所看到的,這個(gè)程序創(chuàng)建了一個(gè)帶有“Hello Device!”字樣的Label控件的窗體。我總結(jié)出該程序需要使用內(nèi)存的六種情況。
Native code pages for the CLR dlls.Compact Framework CLR由兩個(gè)DLL組成,分別是mscoree.dll和mscoree2_0.dll。這兩個(gè)DLL連同Compact Framework的Windows Forms實(shí)現(xiàn)Nativenetcfagl2_0.dll,被成為系統(tǒng)DLL。因此這些DLL的代碼被加載到system code space。Application and Class Library assemblies.CLR必須將應(yīng)用程序和它需要的類庫的所有IL代碼加載到內(nèi)存中,在產(chǎn)生相應(yīng)的本地代碼指令或類加載器展開該類型的數(shù)據(jù)結(jié)構(gòu)時(shí),訪問需要的元數(shù)據(jù)時(shí),使JIT編譯器可以訪問到IL。程序集除了包含“Hello World”代碼外,mscorlib所需要的IL還包括System、System.Windows.Forms和System.Drawing。如果需要,包含這些程序集的文件將被內(nèi)存映射到高位內(nèi)存區(qū)域中。
JIT-compiled native code.當(dāng)一個(gè)應(yīng)用程序被執(zhí)行時(shí),每個(gè)方法被訪問時(shí),JIT編譯器將被調(diào)用,生成本地代碼。本地代碼將被存儲(chǔ)在進(jìn)程虛擬地址空間的一個(gè)buffer里。Allocated reference types.上面分配引用類型的列表中,除了主窗體本身外,還有MainMenu、Label、Point和Size的實(shí)例被創(chuàng)建。更多類型在類庫實(shí)例化時(shí)被創(chuàng)建。所有引用類型所需要的內(nèi)存來自垃圾收集堆。GC堆是應(yīng)用程序自己擁有的堆,存儲(chǔ)在應(yīng)用程序指定的地址空間中。In-memory representation of type metadata.在執(zhí)行一個(gè)程序時(shí)需要用到類和方法,CLR從程序集拷貝中讀取他們的元數(shù)據(jù),并將它們映射到高位地址空間中。元數(shù)據(jù)在使用時(shí)產(chǎn)生類和方法的內(nèi)存中表示(in-memory representation)。該表示被存儲(chǔ)在AppDomain堆中。AppDomain堆被存儲(chǔ)在每個(gè)進(jìn)程的虛擬地址空間中。
Miscellaneous allocations.除了上面討論到的這些內(nèi)存分配類型外,CLR還會(huì)在運(yùn)行程序時(shí)產(chǎn)生一小部分附加數(shù)據(jù)。這類數(shù)據(jù)包括JIT編譯器用來判斷一個(gè)方法是否已經(jīng)被編譯的stub和其他短暫數(shù)據(jù)元素。
現(xiàn)在我們可以看到運(yùn)行托管程序需要用到的數(shù)據(jù)種類,讓我們將它們映射回Windows CE內(nèi)存模型中去。圖2表示的就是每種運(yùn)行時(shí)數(shù)據(jù)種類被存儲(chǔ)到Windows CE內(nèi)存的哪個(gè)區(qū)域中。
CLR與操作系統(tǒng)關(guān)系Figure 2
The mapping between Compact Framework memory allocations and the Windows CE memory model.根據(jù)圖2,最重要的是了解哪些內(nèi)存是分配在每個(gè)進(jìn)程的空間中,而哪些是被所有進(jìn)程共享?;氐角斑呂覀儗indows CE內(nèi)存模型的討論,我們知道,被加載到系統(tǒng)代碼空間中的代碼頁和所有在高位內(nèi)存地址空間上的內(nèi)存分配都是被所有應(yīng)用程序共享的,而在每個(gè)進(jìn)程空間中的內(nèi)存分配都是該進(jìn)程私有的。因?yàn)檫M(jìn)程中的分配不能共享,如何使用每個(gè)進(jìn)程32MB的虛擬地址空間就是一個(gè)十分重要的事情。所以我們決定CLR將jitted代碼、引用類型、in-memory type representations和其他小的內(nèi)存分配都放在進(jìn)程空間內(nèi)。更多關(guān)于進(jìn)程堆尺寸的信息可以參考Mike Zintel的Blog Advanced Compact Framework Memory Management。
現(xiàn)在我們討論了基礎(chǔ)話題,下一文我們將討論.Net Compact Framework JIT編譯器的一些基本設(shè)計(jì)思想。
【編輯推薦】