天天看點

[翻譯]設計.Net Compact Framework CLR(一)

老狼的話:很久沒有翻譯文章了,不過第一眼看到Steven Pratschner的這篇文章時就覺得很有價值。這位老兄目前是微軟.Net Compact Framework Team的成員,這篇文章在CLR設計的高度為我們講述了CLR與作業系統之間的關系,十分值得一讀。目前這位老兄的系列文章已經寫到了第三章,我會在稍後繼續為大家翻譯後邊的部分。大家可以在這裡看到這篇文章的英文原版:http://blogs.msdn.com/stevenpr/

第一章:概述

過去幾周,我一直在寫一系列文章,來讨論建立.Net Compact Framework CLR時不同的設計結果是如何作出的。在第一章中,我讨論影響設計的環境因素,并提供CLR記憶體管理的概述。下面幾章我們将詳細讨論JIT編譯器、垃圾回收和類裝入器的主要設計思路,還有分析Compact Framework 應用程式記憶體使用的資訊。

貫穿這個系列,我将着重讨論建立Compact Framework CLR時的設計決定,這些設計與.Net Framework CLR的設計有很大不同。

---------

表面上看起來,.Net Compact Framework是微軟.Net Framework運作時環境的一個直接移植。但在設計的層次上,這兩個産品的相似其實是有意為之,因為這樣會提供相當的好處。Compact Framework和.Net Framework有相同的程式設計模型,使用相同的檔案格式,共享相同的編譯器等等。兩個程式設計環境如此相似的主要好處是,開發者隻要學習一個程式設計環境,就可以友善地在另一個環境上程式設計。例如,如果開發者熟悉.Net Framework,他幾乎不需要花時間就可以學會使用.Net Compact Framework開發裝置應用程式。

無論表面是如何類似,當你深入内部,你就會發現Compact Framework的實作,尤其是CLR元件,與桌面版本的實作完全不同。無須驚訝,Compact Framework的運作環境直接影響着它内部關鍵元件的架構。兩個主要的環境因素影響了Compact Framework CLR的設計,第一是CLR需要運作在少量的記憶體環境中,第二是需要友善地跨越處理器和作業系統。

這個系列文章,通過了解對設計産生影響的限制條件,來讨論CLR的内部工作機制。通過這個系列我将指出CLR的哪些設計做了不同于桌面版本的修改,使托管代碼能夠運作在記憶體受限的環境中。

了解CLR的内部機制看起來是一個深奧的話題,但是對于你程式下面的平台如何工作有一個清晰的了解,會幫助你了解你的應用程式是如何使用裝置的資源,也會幫你判斷記憶體管理或性能相關的問題。

Compact Framework運作在許多不同的作業系統上,但是大部分是安裝在Windows CE上的。讓我們首先來了解一下Windows CE的記憶體機制。了解作業系統提供給Compact Framework的服務,将幫助我們了解Compact Framework團隊在建構CLR時所作出的決定。

The Windows CE Memory Model

作為一個32位作業系統,Windows CE可以尋址4GB的虛拟位址空間,這方面和桌面版Windows是一緻的。事實上,記憶體空間的劃分對于Windows CE應用程式架構是有直接影響的。為了解決Windows CE應用程式通路記憶體的問題,每個應用程式隻能操作32MB的虛拟位址空間。記憶體可以被配置設定到這32MB空間之外,但是這些記憶體是裝置上所有應用程式共享的,這些配置設定的記憶體不是應用程式私有的。我們在這裡隻對Windows CE的記憶體模型進行一個簡單介紹,使我們能夠了解Compact Framework是如何通路記憶體的。關于Windows CE記憶體模型更詳細的描述可以參考Doug Boling的《Programming Windows CE》(中文版名稱《Windows CE程式設計》)。

下面的圖描述了Windows CE應用程式可用的記憶體區域。

[翻譯]設計.Net Compact Framework CLR(一)
Figure 1

Memory available to Windows CE applications

正如我們所看到的,當程式運作時,會用到三個記憶體空間區域。

  • System Code Space. 裝載系統DLL的隻讀代碼頁,比如coredll.dll。這是每個裝置的系統代碼空間,是以所有應用程式共享該代碼頁。如果需要,Windows CE可以交換這個記憶體區域到儲存設備以壓縮空間。
  • Per-Process Address Space. 每個Windows CE程序被配置設定了32MB的虛拟記憶體。每個線程的棧位址空間、應用程式可執行檔案的代碼頁和任何堆配置設定和使用的空間都存儲在這個空間中。
  • High Memory Area. 這1GB的高段記憶體區域為大量的虛拟記憶體請求提供了虛拟位址空間。任何對VirtulaAlloc的調用請求的虛拟記憶體空間将被配置設定到這部分空間中。另外,所有的記憶體映射檔案将被存儲在高段記憶體中。所有存儲在高位址記憶體區域中的資料對裝置上的所有應用程式可見。如果需要,Windows CE可以将将高位址記憶體區域交換分頁到儲存設備中。

當程式運作時,.Net Compact Framework從這三個區域中擷取需要的記憶體。正如我們所見,為了給托管應用程式的開發者提供最佳體驗,Compact Framework管理每個程序的位址空間。

.NET Compact Framework Memory Management Basics

提高開發者生産力是促使.Net Framework和.Net Compact Framewok被廣泛采用的主要原因。對于CLR提高開發者生産力的讨論經常圍繞着自動記憶體管理(垃圾收集)、程序獨立等話題展開。Compact Framework除了明确提供了這些功能外,也提供了更多幫助開發者提高移動裝置程式開發生産力的更多功能。特别是.Net Compact Framework CLR代替開發者管理每個程序的32MB虛拟記憶體空間。是以開發者就不必為他們的程式在32MB空間中配置設定或釋放記憶體而擔心了。Compact Framework使編寫記憶體受限裝置上的應用程式變得簡單。我們将看到,在這個系列文章中,許多建構.Net Compact Framework CLR的關鍵設計決定就是為了有效地管理每個程序32MB的虛拟記憶體空間。Windows CE将每個程序限制到一個小的虛拟位址空間中,而Compact Framework團隊所要做的事情就是設計一個平台,讓應用程式在給定的空間中運作得更好。

在描述允許在記憶體受限裝置上的設計細節前,我們需要先來看一下,當執行一個托管程式時,作業系統和CLR建立的所有運作時資料。在我讨論完運作一個程式需要的資料種類後,我将告訴大家CLR會将哪些運作時資料配置設定到Windows CE的哪個記憶體區域中去。我們首先來考慮“Hello World”程式運作時,運作時資料的哪些種類需要記憶體。

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);

        this.Menu = this.mainMenu1;

        this.MinimizeBox = false;

        this.Text = "Simple App";

    }

}

    static class Program

    {

        static void Main()

        {

            Application.Run(new Form1());

        }

    }

}

正如你所看到的,這個程式建立了一個帶有“Hello Device!”字樣的Label控件的窗體。我總結出該程式需要使用記憶體的六種情況。

  • Native code pages for the CLR dlls. Compact Framework CLR由兩個DLL組成,分别是mscoree.dll和mscoree2_0.dll。這兩個DLL連同Compact Framework的Windows Forms實作的Native部分,netcfagl2_0.dll,被成為系統DLL。是以這些DLL的代碼被加載到system code space。
  • Application and Class Library assemblies. CLR必須将應用程式和它需要的類庫的所有IL代碼加載到記憶體中,在産生相應的本地代碼指令或類加載器展開該類型的資料結構時,通路需要的中繼資料時,使JIT編譯器可以通路到IL。程式集除了包含“Hello World”代碼外,mscorlib所需要的IL還包括System、System.Windows.Forms和System.Drawing。如果需要,包含這些程式集的檔案将被記憶體映射到高位記憶體區域中。
  • JIT-compiled native code. 當一個應用程式被執行時,每個方法被通路時,JIT編譯器将被調用,生成本地代碼。本地代碼将被存儲在程序虛拟位址空間的一個buffer裡。
  • Allocated reference types. 上面配置設定引用類型的清單中,除了主窗體本身外,還有MainMenu、Label、Point和Size的執行個體被建立。更多類型在類庫執行個體化時被建立。所有引用類型所需要的記憶體來自垃圾收集堆。GC堆是應用程式自己擁有的堆,存儲在應用程式指定的位址空間中。
  • In-memory representation of type metadata. 在執行一個程式時需要用到類和方法,CLR從程式集拷貝中讀取他們的中繼資料,并将它們映射到高位位址空間中。中繼資料在使用時産生類和方法的記憶體中表示(in-memory representation)。該表示被存儲在AppDomain堆中。AppDomain堆被存儲在每個程序的虛拟位址空間中。
  • Miscellaneous allocations. 除了上面讨論到的這些記憶體配置設定類型外,CLR還會在運作程式時産生一小部分附加資料。這類資料包括JIT編譯器用來判斷一個方法是否已經被編譯的stub和其他短暫資料元素。

現在我們可以看到運作托管程式需要用到的資料種類,讓我們将它們映射回Windows CE記憶體模型中去。圖2表示的就是每種運作時資料種類被存儲到Windows CE記憶體的哪個區域中。

[翻譯]設計.Net Compact Framework CLR(一)
Figure 2

The mapping between Compact Framework memory allocations and the Windows CE memory model.

根據圖2,最重要的是了解哪些記憶體是配置設定在每個程序的空間中,而哪些是被所有程序共享。回到前邊我們對Windows CE記憶體模型的讨論,我們知道,被加載到系統代碼空間中的代碼頁和所有在高位記憶體位址空間上的記憶體配置設定都是被所有應用程式共享的,而在每個程序空間中的記憶體配置設定都是該程序私有的。因為程序中的配置設定不能共享,如何使用每個程序32MB的虛拟位址空間就是一個十分重要的事情。是以我們決定CLR将jitted代碼、引用類型、in-memory type representations和其他小的記憶體配置設定都放在程序空間内。更多關于程序堆尺寸的資訊可以參考Mike Zintel的Blog Advanced Compact Framework Memory Management。

現在我們讨論了基礎話題,下一章我們将讨論.Net Compact Framework JIT編譯器的一些基本設計思想。

This posting is provided "AS IS" with no warranties, and confers no rights.

繼續閱讀