Mono

**Mono** 是一個由 Xamarin 公司（先前是 Novell，最早為 Ximian）所主持的自由開放原始碼專案。該專案的目標是建立一系列符合 ECMA 標準（Ecma-334（頁面存檔備份，存於網際網路檔案館）和 Ecma-335（頁面存檔備份，存於網際網路檔案館））的.NET 工具，包括 C# 編譯器和通用語言架構。與微軟的.NET Framework（共通語言執行平臺）不同，Mono 專案不僅可以執行於 Windows 系統上，還可以執行於 Linux、FreeBSD、Unix、OS X 和 Solaris，甚至一些遊戲平台，例如：Playstation 3、Wii 或 XBox 360。Mono 的標誌是一個猴子格式的臉。

Mono 現由 Novell 持有雙重授權，這和 Qt 和 Mozilla Application Suite 的情況相似。Mono 的 C# 編譯器及其相關工具釋出於 GNU 通用公眾授權條款（GPL）之下，其執行時庫釋出於 GNU 較寬鬆公共許可證（LGPL）之下，其類別館釋出於 MIT 授權條款之下。這些均是開源協定因此 Mono 是一個開源軟體。

微軟開發了一個稱為通用語言架構（Shared Source Common Language Infrastructure，Shared Source CLI；即今 ECMA— 通用語言架構）的可用於 FreeBSD，Windows 和 Mac OS X 的.NET 實現版本。微軟的共享原始碼協定並不是開源軟體協定，且可能對於社群來說也是不足夠的（它明文禁止了對軟體的商業用途）。另外，GNU 也有一個.NET 實現版本 Portable.NET 專案，該專案與 Mono 專案有著很多相同的目標。

Mono 虛擬機器包含一個即時編譯引擎，該引擎可用於如下處理器：x86、SPARC、PowerPC、ARM、S390（32 位元模式和 64 位元模式）、x86-64、IA-64 和 64 位元模式的 SPARC。該虛擬機器可以將代碼編譯為本機代碼。

## 歷史

當 Microsoft 在 2000 年 6 月第一次公佈.NET Framework 時，它被描述為一個以網際網路標準為基底的新的平台。並且在 12 月發表了基本的共通語言架構開放標準的形式（ECMA-335），提供了無相依性實作的可能。Ximian 的
米格爾・德伊卡薩在.NET 的文件於 2000 年 10 月釋出時就馬上對.NET 產生了興趣。在檢視位元組碼直譯器後，他發現對於元資料（metadata）沒有相應的說明文件。2001 年 2 月，德伊卡薩在.NET 郵寄清單中索要到了那段缺失了的關於元資料檔案格式的資訊，並開始了採用 C# 編寫一個 C# 編譯器的工作，作為對 C# 的實踐。2001 年 4 月 ECMA 公布了那段缺失的檔案格式，而在 GUADEC（2001 年 4 月 6 日－4 月 8 日）德伊卡薩展示了他的編譯器的一些特性（那個時候他的編譯可以解釋自身）。

Ximian 內部對如何建立能有效提升生產效率的工具進行了大量的討論，他們的目標是通過這些建立出來的工具讓使用者可以在更短時間內建立出更多的應用程式從而縮短開發周期和降低開發成本。經過可行性研究後，他們清楚地見到建立這樣的一項技術是可行的，於是 Ximian 從其它的專案抽調人員並建立了 Mono 的開發小組。由於缺少人力來建立整個.NET 替代產品，他們在 2001 年 7 月 19 日的歐萊禮大會建立了 Mono 的開源專案。

差不多三年後，Mono 於 2004 年 7 月 30 日釋出了 1.0 版本。Mono 逐步從一開始的重點為 Linux 桌面應用程式開發者平台，到支援寛廣範圍的架構和作業系統，包含了嵌入式系統。

在 2011 年 4 月，Attachmate 收購 Novell 後，針對 Novell 發布了上百位人力的解僱。在 3 月 16 號德伊卡薩在他的 blog 發佈在被 Novell 解僱後，他找到一家公司將透過 Xamarin 繼續支援 Mono。原本的 Mono 團隊也被移到新的公司。Xamarin 計畫維持在 Mono 的工作。由於在這時間點 Novell 仍然擁有 MonoTouch 和專為 Android 的 Mono，所以計畫針對 iOS 和 Android 上重寫商業化的.NETstacks。

在這發表之後，這個專案的未來被質疑。因為，專屬 Android 的 MonoTouch and Mono 變成跟現存 Attachmate 所屬的商業化商品有直接競爭，也考量了 Xamarin 團隊為了相同的作品而不使用之前在 Novell 開發的技術，證實是有困難的。無論如何，在 2011 年七月 Novell、Attachmate 的子公司及 Xamarin 發表了對 Xamarin for Mono, MonoTouch and Mono for Android 的永久性授權條款，正式地帶起這個案子的管理方式。

## 目前的狀況與藍圖

Mono 目的的版本為 3.10.0（2014 年 10 月）。這個版本提供了.NET Framework 的核心 API、Visual Basic .NET 的支援、C# 版本 2.0,3.0，及 4.0、LINQ to Objects、XML 及 SQL 等。在 C# 編譯器的目前操作的預設模式是 C# 4.0。Windows Forms 2.0 也有被支援，但沒有積極地被開發，因此，它在 Mono 的支援不完整。Mono 的目標是達成在.NET 4.0 的完整功能支援，除了 Windows Presentation Foundation（WPF）和 Limited Windows Communication Foundation（WCF）。
在實驗性質 mono 的開發.NET Framework 的一些遺失部份稱做 Olive
Mono 專案也建立了 Visual Basic .NET 編譯器與一個 runtime 的 VB.NET 的應用程式。它目前一直由 Rolf Bjarne Kvinge 進行開發。

### Moonlight

Moonlight 是一個 Microsoft Silverlight 的開源實作，自從 Mono 1.9 起即包含了這實作。在 2009 年 1 月 20 日釋出的 Moonlight 1.0 支援 Silverlight 1.0 APIs。而 Moonlight 2.0 支援 Silverlight 2.0。Moonlight 3.0 則在 2010 年 2 月被發表，包含了 Silverlight 3.0 的支援。Moonlight 最終在 2012 年 3 月 29 日被放棄。依據米格爾所言，兩個因素扼殺了這個專案的命運：Microsoft 增加了「人為限制」... 這造成了桌面程式無用武之地..."，並且在 Web 上的技術沒有獲得足夠的配合。

## Mono 組成元件

Mono 組成元件包含了以下三類：

1. 核心元件
2. Mono/Linux/GNOME 開發堆疊
3. 微軟相容堆疊

_核心元件_包含了 C# 編譯器，Common Language Infrastructure 虛擬機器，以及核心類別程式庫。這些元件都是基於 Ecma-334 and Ecma-335 標準，而使得 Mono 能夠提供與標準相容、免費、並且是開放原始碼的 CLI 虛擬機器。微軟曾經聲明這些標準都是基於 Community Promise license 的社群保護承諾之下。

_Mono/Linux/GNOME 開發堆疊_則是提供了工具以用於開發應用軟體。這些工具使用了既有的 GNOME 以及自由並且開放原始碼程式庫，它們包含了針對圖形使用者介面（GUI）開發的 Gtk#、可套用 Gecko rendering engine 的 Mozilla 程式庫、Unix 整合程式庫（Mono.Posix）、安全性推疊、以及 XML schema 語言 RelaxNG。Gtk# 讓 Mono 應用程式融入 Gnome 桌面環境而成為原生程式。資料庫程式庫則提供了與物件關連式資料庫連結的能力，這些資料庫包含了 db4o、Firebird、Microsoft SQL Server（MSSQL）、MySQL、Open Database Connectivity（ODBC）、Oracle、PostgreSQL、SQLite 等等。在網站上可看見 Mono 專案一直都在持續更新維護資料庫程式庫。

_微軟相容堆疊_則是提供了一種方式來使得 Windows .NET 應用程式可以被移植到 GNU/Linux 上。這個堆疊包含了 ADO.NET、ASP.NET 以及 Windows Forms 等等。不過，由於這些元件並沒有被上述所說 Ecma 標準所涵蓋，因此部份元件有所謂專利恐懼與疑慮的問題。

## 架構

### 程式執行引擎

Mono 程式的執行包含一個程式碼運作引擎，它會將 ECMA CIL 的 byte code 轉譯為原生碼（Native Code），它支援了以下處理器：ARM、MIPS（只有 32 位元模式）、SPARC、PowerPC、S390（64 位元模式）、x86、x86-64 以及 IA-64 64 位元模式。

程式的轉譯有三種模式：

* Just-in-time (JIT) 編譯：在程式執行當中將 ECMA CIL 的 byte code 轉譯為原生碼。
* Ahead-of-Time (AOT) 編譯：ECMA CIL 的 byte code（通常在.exe 檔或.dll 檔中）會轉譯出原生碼並儲存在作業系統中、以及 CPU 架構設定檔（例如在 Linux 上，如果是 foo.exe，就會產生 foo.exe.so 檔）。通常，此種模式可產生出絕大部份前種模式所產生的原生碼，部份的例外是 trampolines 或是控管監督相關的碼（仍舊需要 JIT 來執行），由此可知 AOT 影像檔並非可以完全獨立執行的。
* 完全靜態編譯：這個模式只支援少數平台，它基於 AOT 編譯模式上，更進一步產生所有的 trampoline、wrappers 以及 proxies，這幾樣東西是用於靜態連結出靜態檔案時所需。完全靜態編譯模式可以讓程式的執行期完全不需要用到 JIT，這個做法適用於 Apple iOS 作業系統、Sony PlayStation 3 以及微軟的 XBox 360 等作業系統。

從 2.6 版起，Mono 開始支援使用 LLVM 來產生執行碼，而非原本內建的方式。這對於高效能計算方面非常有用，因為在這種場合下，程式的執行效能比啟動速度來得重要。

從 2.7 Preview 版開始，使用者不再需要在程式編譯前的 Configuration 時就必須選定執行碼產生引擎，執行碼的產生可以在程式啟動時以 `--llvm` 或 `--nollvm` 的參數來指定即可，預設是以內建的引擎為主，因為它的產生速度比較快。

### 垃圾回收

當 2.8 版推出時，Mono runtime 提供了兩套垃圾回收器：generational collector 以及 Boehm conservative collector。在 Mono 3.1.1 版之前，預設的垃圾回收器（_Boehm-Demers-Weiser Conservative Garbage Collector_），跟商業環境如 Java Virtual Machine 或.NET framework 的垃圾回收器相比，一直有很大的限制，在某些狀況的應用軟體上會發生記憶體流失的現象，這使得 Mono 無法用於需要長時間執行的伺服器應用。

截至 2010 年 10 月 (2010-10)，一個稱之為「Simple Generational GC」（SGen-GC）的新一代垃圾回收器開始用於 Mono 中，在 3.1.1 版之後就直接變成是預設的垃圾回收器。對於 Mono 2.8 到 3.1.0，使用者可以以傳入參數 `--gc=sgen` 來讓 Mono runtime 啟動時使用 SGen 垃圾回收器。這個新的垃圾回收器相較於傳統基於保守型掃描方式的回收器，有很多優點，它使用了 generational garbage collection，從物件一開始被組態、到各個週期，所有活著的物件都會被轉移到較早代的記憶體池，這個想法是來自於因為許多物件都只是短暫使用的，因此可以被快速回收再利用，只有少數物件是長期性的存活在應用程式的整個生命期中。另外，為了改善效率，這個回收器對每個執行緒組態了個別的記憶體池，讓執行緒不需要跟別的執行緒打交道就可以自行組態記憶體區塊。對於前述所說，物件的轉移到較早代記憶體池的做法則是，在轉移之後，將所有目前指向該物件的指標都更新為新的位址。由於這樣的做法在大型物件時比較浪費記憶體，因此 SGen 為大型物件使用了獨自的記憶體池（Large Object Section），並且對這些物件使用 mark-and-sweep 演算法。

目前 SGen 是以比較保守的方式來對待堆疊與暫存器，並且，那些可被參考到的物件是由它們的 root 來負責 pin 的動作。未來版本的 Mono 將會以精確方式來掃描代管的堆疊，藉此減少那些被 pin 的物件。

### 類別庫

類別庫為應用程式開發提供一套廣泛而有效的工具類。這些工具類可以用於任何.NET 語言。類別庫被按命名空間進行了結構化，並被放置於稱為程式集的共享庫中。在我們談到.NET Framework 時，我們多數是指這個類別館。

#### 命名空間和程式集

命名空間是一種用於將邏輯上相似的類按階層分組的機制。這種機制防止了命名衝突。在這種結構化採用被點號 "." 分隔的單詞來實現。通常最頂層的命名空間是 System，例如 System.IO 和 System.Net（完整的命名空間列表可以在 Mono 文件（頁面存檔備份，存於網際網路檔案館）中找到）。當然還有別的頂層命名空間，例如 Accessibility 和 Windows 就是這樣的例子。新建的命名空間還可以以開發組織的名字開頭。

**程式集**是這些類別館的物理載體。它們跟 Win32 共享庫一樣都是 dll 檔案，儘管不完全一樣。一些程式集的例子有：mscorlib.dll，System.dll，System.Data.dll 和 Accessibility.dll。命名空間經常被分拆到幾個程式集中，而一個程式集可以由幾個檔案組成。

### 公共語言基礎和公共語言規範

公共語言基礎（Common Language Infrastructure，CLI）是一套標準（ECMA335），公共語言執行時（Common Language Runtime）即 CLR 是 CLI 標準的實現，Mono 是實現者之一。該執行時用於執行已編譯的.NET 應用程式。公共語言基礎已被 ECMA 定義為標準 ECMA-335。要執行一個.NET 應用程式，你必須使用相應的參數呼叫執行時。

在 ECMA-335 的第六章詳細說明了「公共語言規範」（Common Language Specification，CLS）並定義了提供給公共語言基礎的介面，例如對於列舉類型的隱含表示類型的協定。Mono 的編譯器負責生成符合公共語言規範的對映代碼，即公共中間語言（Common Intermediate Language，CIL）。Mono 的執行時將執行這類代碼。ECMA 標準先前還定義了一個符合公共語言規範的程式庫作為應用框架。

### 代管與非受控代碼

在原生的.NET/Mono 應用程式中，所有代碼都是代管的，也就是說，是受管於 CLI 式的記憶體管理和執行緒安全管理的。其它的.NET 或 Mono 應用程式可以通過使用 System.InterOpServices 庫建立 C# 繫結來呼叫已存的非受控代碼。很多移植到 Mono 的類別館使用了 CLI 的這個特性，例如 Gtk#。

### 相關專案

現有大量與 Mono 相關的用於擴充 Mono 的專案，這些專案允許開發者在他們的開發環境中使用 Mono。這些專案包括：

* Cocoa#（頁面存檔備份，存於網際網路檔案館），對原生 Mac OS X 工具包的一系列包裝（Cocoa）。
* Gecko#，一個對在 Mozilla 中使用的嵌入式布局引擎的繫結（Gecko）。
* Gtk#，對使用 C 的 GTK + 庫的 C# 的外包。
* Tao，一個圖形及遊戲庫的繫結。

## 授權

Mono 是透過 Xamarin 的雙重授權，相似於其他產品，如 Qt 和 Mozilla application Suite。Mono's C# 編譯器與工具是依照 GNU Leasser General Public License（LGPLv2 only）來釋出（開始於 Mono 2.0，Mono C# 的編譯器原始碼在 MIT X11 License 仍然是有效的），屬於 GNU Leasser General Public License（LGPLv2 only）的 runtime 函式庫及屬於 MIT X11 License 的類別函式庫。

有完全免費的軟體與開源授權，因此 Mono 是免費的開源軟體。

C# 編譯器的授權改變是從 GPL 到 MIT X11 授權，允許編譯器的程式碼在少許的 GPL 限制例子中被重複使用，如例：

* 作為服務的 Mono 編譯器

```
 * Mono互動介面的Shell
 * Mono可崁入的的C#編譯器
```

* Mono 的 C# 4.0 的動態綁定的實作
* MonoDevelop 的內建 parser 和 AST 圖

## Mono 與微軟的專利

人們對於微軟能否採用專利摧毀 Mono 專案進行了大量的爭論。其實，專利問題不在於已被提交到 ECMA 組織的核心技術或 Unix/Gnome 的專有部分，而在於由微軟基於.NET Framework 建立的技術，例如 ASP.NET、ADO.NET 和 Windows Forms。這些技術在 Mono 中至今還沒有被完全地實現，事實上，在開發 Mono 應用程式時也不需要用到，然而，在開發基於 Windows 平台的程式時卻是不可缺少的。Mono 團隊將目標定為將這些技術納入到專案中，並制訂了一個三步驟策略來處理它們：

1. 採用其它實現方式來實現從而繞過專利問題
2. 把包含專利的代碼清除出專案
3. 找出「現有技術（prior art）」從而將專利變為非專利

顯然，第一個選項並不總是可行的。對於一些問題，例如那些與協同工作和互動相關的，可能就只有一種解決方案。由於這個相同的原因，儘管第二個選項總是可行的，它卻可能導致一個開發出來的產品並不能作為.NET 的替代品。第三個選項則是昂貴的，甚至不可能的，這需要一定程度的運氣。

## 使用 Mono 開發的軟體

以下是使用 Mono API 和 C# 編寫的部分程式：

* Banshee 是一個用於 GNOME 的音樂管理和播放軟體。
* Beagle 是一個桌面搜尋軟體。
* Blam! 是一個 RSS 新聞聚集器，特別適合於閱讀如 Planet Gnome（頁面存檔備份，存於網際網路檔案館）這樣的行星（頁面存檔備份，存於網際網路檔案館）資訊。
* Bless（頁面存檔備份，存於網際網路檔案館）是一個十六進位編輯器。
* CDCollect（頁面存檔備份，存於網際網路檔案館）是一個 CD 編目應用程式。
* Diva 是一個用於 GNOME 的影片編輯器。
* F-Spot 是有個由 Novell 開發的圖片便捷管理程式。
* Fiddler（頁面存檔備份，存於網際網路檔案館）是一個強大的 Web 抓包工具，與 Charles 齊名。
* Galaxium（頁面存檔備份，存於網際網路檔案館）是一個 MSN 即時通訊軟體客戶端。
* GLyrics 是一個歌詞搜尋器。
* Gpremacy（頁面存檔備份，存於網際網路檔案館）是以 Mono/Gtk# 實作的圖版遊戲 Supremacy
* iFolder 3（by Novell）讓你使用對等協定（peer-to-peer）或 Novell 的群集伺服器產品與其它電腦和使用者共享檔案。
* imeem（頁面存檔備份，存於網際網路檔案館）一個社交網路軟體。Mac 版本的使用者端和伺服器使用 Mono 運行，而 Windows 版本的使用者端仰賴於 Microsoft.Net
* KeePass 是一款開源的密碼管理器。
* MindFire 是一個用於輔助速讀（speed reading）的跨平台電子書閱讀器
* MonoDevelop 是一個用於建立 Mono 應用程式的整合式開發環境。該軟體原先是 SharpDevelop 向 Gtk# 的一個移植，而現今該軟體已獨立開發。該軟體在 Windows 上有測試版的可用版本。
* Pinta 是一個簡單的點陣圖形編輯軟體。

## 分支版本

2011 年 4 月，Novell 公司被 Attachmate 公司所併購，而原先在 Novell 公司裡的 Mono 開發者被大量資遣。2011 年 5 月，原先 Mono 的開發者另外成立一家 Xamarin 的公司，仿 Mono 發行他們的 Xamarin 跨平台.NET 套件，在 Windows 下能與整合到 Microsoft Visual Studio 的 IDE 之中。2011 年 7 月，Attachmate 公司旗下的 Novell 公司批准了 Mono 相關專案到 Xamarin 的授權。

## 備註

1. **^** For more information about the licensing, see Mono FAQ: Licensing（頁面存檔備份，存於網際網路檔案館）

## 參考文獻

* _This article incorporates text from Mono's homepage（頁面存檔備份，存於網際網路檔案館），which is in the GNU Free Documentation License._
* Miguel de Icaza. [Mono-list] Mono early history.. 2009-10-13 [6 December 2005]. （原始內容 (mailing list) 存檔於 2011-06-06）.
* Eugenia Loli-Queru. Mono Applications? Aplenty!. OSNews. 2005-02-22 [6 December 2005]. （原始內容存檔於 2006-11-11）.

## 外部連結

* GotMono?,（頁面存檔備份，存於網際網路檔案館） Mono community homepage
* Mono Forum
* Mono Live（頁面存檔備份，存於網際網路檔案館），LiveCD website
* Running .NET on Linux or Windows
* Ximian Forum
* Slashdot: Fedora Core 5 includes Mono（頁面存檔備份，存於網際網路檔案館）
* Novell, Inc.（頁面存檔備份，存於網際網路檔案館）

**國際站點**

* Mono France，A French Mono WebSite
* MonoBrasil，A Brazilian Mono WebSite
* MonoColombia，A Colombian Mono WebSite
* MonoGermany（頁面存檔備份，存於網際網路檔案館），A German Mono WebSite
* MonoHispano，A Spanish Mono community
* Japanese Mono Mono web site translation to Japanese.
* MonoPoland，Polish Mono Web site.
* Mono Netherlands，Dutch Mono site.