これは古い質問です (すでに回答が選択されています) が、その質問が本当に適切に回答されているとは思えません。
まず、背景を少し...
.NET はどのように機能しますか?
従来の Windows .EXE ファイルはバイナリ ファイルであり、コンピューターが理解できる一連の機械語命令を表し、アプリケーションが利用できるサービスを提供する Windows の一部である Win32 API を呼び出します。使用される機械語は、お使いのコンピューターの種類に非常に固有のものであり、Win32 呼び出しにより、実行可能ファイルは Windows に大きく依存します。.NET 実行可能ファイルはそうではありません。
.NET 実行可能ファイル (.EXE ファイル) は、実際にはネイティブ Windows アプリケーションではないことに注意してください。Windows 自体は、.NET 実行可能ファイルでコードを実行する方法を理解していません。あなたのコンピュータもそれを理解していません。
Java と同じように、.NET アプリケーションは CIL (Common Intermediate Language) と呼ばれる言語の命令で構成されています。CIL は、実際には存在しない理想化されたコンピューターの機械語と考えることができます。.NET では、この理想化されたマシンのソフトウェア実装は、共通言語ランタイム (CLR) と呼ばれます。Java の世界でこれに相当するものは、Java 仮想マシン (JVM) と呼ばれます。Java では、CIL に相当するものを Java バイトコードと呼びます。CIL は MSIL (Microsoft Intermediate Language) と呼ばれることもあります。
CIL は CLR (理想化されたマシン) で実行するように設計されていますが、それ以外はプラットフォームに依存しません。つまり、CIL は使用しているコンピューターの種類や実行しているオペレーティング システムを気にしません。
Java を実行する各プラットフォームで Java JVM のネイティブ バージョンが必要なのと同様に、.NET CIL 実行可能ファイルを実行するには CLR のネイティブ バージョンが必要です。CLR は、前述の従来の Win32 EXE ファイルと同様のネイティブ Windows アプリケーションです。CLR 自体は、それを実行するように設計された Windows の実装とコンピューター アーキテクチャに固有のものです。
どの .NET 言語 (C#、VisualBasic、F#、IronPython、IronRuby、Boo など) から始めても問題ありません。それらはすべて CIL バイトコードにコンパイルされます。CIL プログラムは、人間が簡単に読み取れるオブジェクト指向アセンブリ言語の形式に簡単に「逆アセンブル」できます。CIL でプログラムを直接自分で書くことはできますが、そうする人はほとんどいません。
Windows では、CLR は、実行可能ファイルを実行するとき、つまりコードが実際に実行される直前に、この CIL コードを Just-in-Time (JIT) にコンパイルします。これは、CIL バイトコードが、コンピューター上でネイティブに実行される実際のマシン コードに変換 (コンパイル) されることを意味します。CLR のこの部分は、JIT コンパイラーまたは単に JIT と呼ばれることもあります。
これまでに、Microsoft は CLR の 4 つのバージョン (1.0、1.1、2.0、および 4.0) をリリースしました。そのランタイムを対象とする .NET 実行可能ファイルを実行する場合は、適切なバージョンの CLR がマシンにインストールされている必要があります。CLR 2.0 は、.NET 2.0、3.0、および 3.5 アプリケーションをサポートします。.NET の他のバージョンの場合、.NET バージョンは CLR バージョンに完全にマップされます。
JIT/CLR に加えて、.NET は、.NET フレームワークの残りの部分を構成し、.NET アプリケーションが呼び出すことができる多くの機能とサービスを提供するライブラリ (アセンブリ) のホストを提供します。これらのアセンブリの大部分は、CLR で実行される純粋な CIL コードです。Windows では、Win32 API への make 呼び出しもあります。.NET をインストールすると、CLR、クラス ライブラリ (フレームワーク)、および一連の開発ツールがインストールされます。通常、CLR の各バージョンには、これらの「フレームワーク」アセンブリの完全なセットが必要です。.NET の一部のバージョン (3.0 および 3.5 など) では、CLR またはその CLR に関連付けられている既存のアセンブリを更新せずに、追加のフレームワーク アセンブリが追加されていました。
Windows .EXE ファイルが提供される Portable Executable (PE) ファイル形式には、実行可能ファイルを記述し、ファイルを .NET ファイルまたはネイティブ Win32 ファイルとして識別するヘッダーが含まれています。Windows が .NET ファイルを実行しようとすると、このヘッダーが表示され、ユーザーに代わって CLR が自動的に呼び出されます。これが、.NET EXE ファイルが Windows でネイティブに実行されるように見える理由です。
では、Mono はどのように機能するのでしょうか。
Mono は、Linux、Mac、およびその他のプラットフォームで CLR を実装します。Mono ランタイム (CLR) は、ほとんどが C 言語で記述されたネイティブ アプリケーションであり、実行するように設計されたコンピューター システム用の機械語コードにコンパイルされます。Windows と同様に、Mono ランタイムはオペレーティング システムと使用しているマシンの種類に固有です。
Windows と同様に、Mono ランタイム (CLR) は、.NET 実行可能ファイル内の CIL バイトコードを、コンピューターが理解して実行できるネイティブ コードにジャストインタイムでコンパイルします。このように、.NET ファイルは、Windows と同様に Linux でも「ネイティブ」です。
Mono を新しいアーキテクチャに移植するには、JIT/CLR を移植する必要があります。これは、ネイティブ アプリケーションを新しいプラットフォームに移植するようなものです。
Linux または Mac で .NET コードがどれだけうまく動作するかは、これらのシステムに CLR がどれだけうまく実装されているかという問題にすぎません。理論的には、Mono CLR は、Windows で MS バージョンの .NET が実行するよりも、これらのシステムで .NET コードを実行できます。実際には、MS の実装は一般的に優れています (すべての場合ではありませんが)。
CLR に加えて、Mono は、.NET フレームワークを構成する残りのほとんどのライブラリ (アセンブリ) を提供します。Microsoft バージョンの .NET と同様に (実際にはそれ以上)、Mono アセンブリは CIL バイトコードとして提供されます。これにより、Windows、Mac、または Linux で CIL が CLR 実装の「ネイティブ」言語であるため、Mono から *.dll または *.exe ファイルを取得し、変更せずに実行できます。
Windows と同様に、Mono は複数のバージョンの CLR と関連するアセンブリをサポートしています。
Mono の非常に初期のバージョン (1.2 より前?) は、CLR 1.0 または 1.1 のみをサポートしていました。Mono は、独自の 2.0 バージョンになるまで、2.0 フレームワークの大きな部分をサポートしていませんでした。
バージョン 2.4 までの Mono バージョンは、CLR 1.1 と CLR 2.0 の両方のアプリケーションをサポートしていました。
Mono 2.6 から、CLR 4.0 が追加されましたが、CLR 2.0 がデフォルトのままでした。
Mono 2.8 以降、CLR 4.0 がデフォルトになり、CLR 1.1 はサポートされなくなりました。
Mono 2.10 は引き続き CLR 4.0 をデフォルトとして使用し、CLR 2.0 をサポートします。
実際の .NET と同じように (ただし、はるかに少ないケースで)、ネイティブ ライブラリを呼び出す Mono アセンブリがいくつかあります。System.Drawing アセンブリを Mono で動作させるために、Mono チームは、Linux 上で Win32 API の GDI+ 部分をシミュレートする Linux プログラムを作成しました。このライブラリは「libgdiplus」と呼ばれます。ソースから Mono をコンパイルする場合、「mono」をビルドする前に、この「libgdiplus」ファイルをビルドする必要があることに気付くでしょう。Win32 API の GDI+ 部分は既に Windows の一部であるため、Windows では「libgdiplus」は必要ありません。Mono を新しいプラットフォームに完全に移植するには、この「libgdiplus」ライブラリも移植する必要があります。
.NET ライブラリの設計が Windows の設計に過度に影響を受け、Mac や Linux などのシステムにあまり適していない領域では、Mono チームは .NET フレームワークの拡張機能を作成しました。Mono 拡張機能も単なる CIL バイトコードであり、通常は .NET 上で問題なく動作します。
Windows とは異なり、Linux は一般に .NET 実行可能ファイルを検出せず、デフォルトで CLR を起動します。ユーザーは通常、「mono appname.exe」などと入力して CLR を直接実行する必要があります。ここで、'mono' は CLR を実装するアプリケーションであり、'appname.exe' は実行する .NET コードを含む EXE ファイルです。
ユーザーが簡単に操作できるように、Mono アプリケーションは多くの場合、CLR を起動するシェル スクリプトにラップされています。これにより、Windows と同様に CLR が使用されているという事実が隠されます。PE ファイル形式を使用するファイルが検出されたときに CLR を起動するように Linux に指示することもできます。PE ファイル形式はネイティブの Win32 Windows 実行可能ファイルにも使用され、もちろん CLR (Mono) はサポートしていないため、これは通常行われません。
PE ランチャーを Linux で使用できない技術的な理由はありません。Linux は、必要に応じてネイティブ Windows コード (Wine など) または CLR (Mono) を理解するシステムを起動します。これは、私の知る限りでは行われていません。
行ったり来たり
「完全に管理された」コードに固執する .NET コードは、.NET 以外のコードを呼び出さないことを意味し、すべてのプラットフォームの Mono で正常に動作するはずです。Linux と Mac では、Windows からコンパイルされた .NET アセンブリ (コードがない) を日常的に使用しています。
また、Mono でコンパイルしたコードを Windows 上の .NET で実行することもできます。Mono でコンパイルしたコードをクライアントに提供できます。たとえば、クライアントが 32 ビットまたは 64 ビットの Windows を使用しているかどうかを心配する必要はありません。もちろん、クライアントには正しいバージョンの .NET (正しい CLR) がインストールされている必要があります。CLR 2.0 は非常に長い間存在しており、ほぼすべての Windows ユーザーが CLR 2.0 をインストールしていることは間違いありません。Mono コンパイラやその他のコードも単なる CIL 実行可能ファイルであるため、必要に応じて Windows 上で正常に動作します。
Mono 互換性は十分に優れているため、ASP.NET MVC などの実際の Microsoft コードの大きなチャンクを、実際の MS バージョンの .NET から取得して (合法的な場合)、Mac または Linux で実行できます。一般に、Mono チームは、CLR とフレームワークの残りの部分 (クラス ライブラリ/アセンブリ) の両方を実装するという素晴らしい仕事をしました。
ASP.NET
Windows では、Internet Information Server (IIS) は、CLR を呼び出して .NET を Web アプリケーションの一部として実行する方法を認識しています。Linux/Mac には、Apache ウェブサーバーと同様の機能を提供する Apache モジュール (mod_mono) があります。このアプリケーションは C で書かれており、新しいアーキテクチャにも移植する必要があります。
ポーティングモノ
この説明では、"ネイティブ" 実行可能ファイルとしてビルドされ、.NET アプリケーションを実行するシステムに存在する必要がある Mono の部分を特定しました。
- CLR (JIT コンパイラを含む) - 一般に Mono として知られている
- libgdiplus (GDI+ API をネイティブにサポートしていないシステム用 [Windows のみサポート])
- mod_mono (Apache が .NET Web アプリケーションの CLR を呼び出せるようにするため)
これら 3 つのコンポーネントにクラス ライブラリを追加すると、実行する必要がある .NET 実行可能ファイルに対して "ネイティブ" に見える .NET 環境が提供されます。
それがモノの仕組みです。