.net 中的託管與非託管到底什麼是託管,什麼是非託管的研究

來源:互聯網
上載者:User
參考文獻

關於託管與非託管

到底什麼是託管,什麼是非託管的研究

前言

最近在看《ASP.NET MVC 4架構揭秘》,裡面有很多微軟.net的東西,其中就很多次提到了託管與非託管,搞得我雲裡霧裡的,今天特地抽空來整理一下。大部分內容都是參考別人的。

Managed 程式碼

Managed 程式碼就是Visual Basic .NET和C#編譯器編譯出來的代碼。編譯器把代碼編譯成中繼語言(IL),而不是能直接在你的電腦上啟動並執行機器碼。中繼語言被封裝在一個叫程式集(assembly)的檔案中,程式集中包含了描述你所建立的類,方法和屬性(例如安全需求)的所有中繼資料。你可以拷貝這個程式集到另一台伺服器上部署它。通常來說,這個拷貝的動作就是部署流程中唯一的一個操作。

Managed 程式碼在公用語言運行庫(CLR)中運行。這個運行庫給你的運行代碼提供各種各樣的服務,通常來說,他會載入和驗證程式集,以此來保證中繼語言的正確性。當某些方法被調用的時候,運行庫把具體的方法編譯成適合本機電腦啟動並執行機械碼,然後會把編譯好的機械碼緩衝起來,以備下次調用(這就是即時編譯)。隨著程式集的運行,運行庫會持續地提供各種服務,例如安全,記憶體管理,線程管理等等。這個程式被“託管”在運行庫中。Visual Basic .NET和C#只能產生Managed 程式碼。如果你用這類語言寫程式,那麼所產生的代碼就是Managed 程式碼。如果你願意,Visual C++ .NET可以產生Managed 程式碼。當你建立一個項目的時候,選擇名字是以.Managed開頭的項目類型。例如.Managed C++ application。

Unmanaged 程式碼

Unmanaged 程式碼就是在Visual Studio .NET 2002發布之前所建立的代碼,例如Visual Basic 6, Visual C++ 6。 最糟糕的是,連那些依然殘存在你的硬碟中、擁有超過15年歷史的陳舊C編譯器所產生的代碼都是Unmanaged 程式碼。Unmanaged 程式碼直接編譯成目標電腦的機械碼,這些代碼只能運行在編譯出它們的電腦上,或者是其它相同處理器或者幾乎一樣處理器的電腦上。Unmanaged 程式碼不能享受一些運行庫所提供的服務,例如安全和記憶體管理等。如果Unmanaged 程式碼需要進行記憶體管理等服務,就必須顯式地叫用作業系統的介面,通常來說,它們會調用Windows SDK所提供的API來實現。就最近的情況來看,非託管程式會通過COM介面來擷取作業系統服務。跟Visual Studio平台的其他程式設計語言不一樣,Visual C++可以建立非託管程式。當你建立一個項目,並且選擇名字以MFC,ATL或者Win32開頭的項目類型,那麼這個項目所產生的就是非託管程式。

總而言之,Unmanaged 程式碼是運行在公用語言運行庫環境(CLR)的外部,由作業系統直接執行的代碼。Unmanaged 程式碼必須提供自己的記憶體回收、類型檢查、安全支援等服務;它與Managed 程式碼不同,後者從公用語言運行庫中獲得這些服務。

兩者區別

對於Visual Basic和C#來說,生活是簡單的,因為你沒有其它選擇。當你在那些語言裡面聲明一個類,那麼這個類的執行個體會在託管堆中被建立,垃圾收集器(GC)會幫我們管理這些對象的回收。但是在Visual C++中,你有另一個選擇。即使你正建立一個託管程式,你可以決定哪些類是託管類型,哪些類是非託管類型的。

非託管類型:
class Foo{   private:      int x;   public:      Foo(): x(0){}      Foo(int xx): x(xx) {}};
託管類型
_gc class Bar{   private:      int x;   public:      Bar(): x(0){}      Bar(int xx): x(xx) {}};

他們唯一的區別就是類Bar的定義中有_gc關鍵字。這個關鍵字會給代碼帶來巨大的區別。

託管類型是可以被記憶體回收行程所回收的。他們必須要用關鍵字new來建立,永遠都不會在棧中出現。所以下面這行代碼是合法的:

Foo f;//非託管類型

但是這一行代碼就是非法的:

Bar b;//託管類型必須用new來建立

如果我在堆中建立一個Foo對象,那麼我必須要負責清理這個對象:

Foo* pf = new Foo(2);// . . .delete pf;//手動清理

C++編譯器實際上會用兩個堆,一個託管堆和一個非託管堆,然後通過對new操作符的重載來實現對建立不同類型類的執行個體,分配不同的記憶體。如果我在堆裡面建立一個Bar執行個體,那麼我可以忽略它。當沒有其他代碼在使用它的時候,記憶體回收行程會自動清理這個類,釋放其佔用的資源。對於託管類型會有一些約束:它們不能實現多重繼承,或者繼承與非託管類型;它們不能用friend關鍵字來實現私人訪問,它們不能實現拷貝建構函式。所以,你有可能不想把你的類聲明為託管類型。但是這並不意味著你不想讓你的代碼成為Managed 程式碼。在Visual C++中,你可以選擇。

Managed 程式碼的執行過程
  1. 選擇編譯器:為獲得公用語言運行庫提供的優點,必須使用一個或多個針對運行庫的語言編譯器,如 Visual Basic、C#、Visual C++、JScript 或許多第三方編譯器(如 Eiffel、Perl 或 COBOL 編譯器)中的某一個。由於運行庫是一個多語言執行環境,因此它支援各種資料類型和語言功能。您所用的語言編譯器首先確定可用的運行庫功能,然後使用這些功能設計代碼。編譯器(而不是運行庫)建立代碼必須使用的文法。如果您的組件必須完全能夠被用其他語言編寫的組件使用,您的組件的匯出類型必須只公開Common Language Specification (CLS) 中包括的語言功能。
  2. 編譯,將原始碼翻譯為microsoft中繼語言(MSIL)並產生所需的中繼資料。
  3. 在執行時,即時 (JIT) 編譯器將 MSIL 翻譯為機器碼。在此編譯過程中,代碼必須通過驗證過程,該過程檢查 MSIL 和中繼資料以查看是否可以將代碼確定為型別安全。
  4. 運行代碼:公用語言運行庫提供使執行能夠發生以及可在執行期間使用的各種服務的結構。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.