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 實現版本專案，該專案與 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 的永久性許可證，正式地帶起這個案子的管理方式。

目前的狀況與藍圖

截止 2024 年 12 月，Mono 更新到了 6.12.0.206 版本，但專案已經由被微軟收購的 Xamarin 移交給 WineHQ，官方建議將現有 Mono 應用程式遷移到同樣開源的.Net 平臺上。

Mono 組成元件

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

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

核心元件包含了 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 標準所涵蓋，因此部份元件有所謂專利恐懼與疑慮的問題。

架構

4.1 程式執行引擎

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 的引數來指定即可，預設是以自帶的引擎為主，因為它的產生速度比較快。

4.2 垃圾回收

當 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 無法用於需要長時間執行的伺服器應用。

，一個稱之為「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 的物件。

4.3 類別庫

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

4.3.1 名稱空間和程式集

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

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

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

公共語言基礎（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 標準先前還定義了一個符合公共語言規範的程式庫作為應用框架。

4.5 託管與非託管程式碼

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

4.6 相關專案

現有大量與 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 團隊將目標定為將這些技術納入到專案中，並制訂了一個三步驟策略來處理它們：

採用其它實現方式來實現從而繞過專利問題
把包含專利的程式碼清除出項目
找出 “現有技術（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 公司被公司所併購，而原先在 Novell 公司裡的 Mono 開發者被大量資遣。2011 年 5 月，原先 Mono 的開發者另外成立一家 Xamarin 的公司，仿 Mono 發行他們的 Xamarin 跨平臺.NET 套件，在 Windows 下能與整合到 Microsoft Visual Studio 的 IDE 之中。2011 年 7 月，公司旗下的 Novell 公司批准了 Mono 相關專案到 Xamarin 的授權。