モノはどのように魔法ですか?


149

私はC#を学んでいるので、と言う小さなC#プログラムをHello, World!作成し、それをコンパイルしてmono-csc実行しましたmono

$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!

私は私が打ったとき気づいTABbashHello.exe実行可能なマークされました。実際、ファイル名をロードするシェルだけで実行されます!

Hello.exe面白いファイル拡張子を持つELFファイルではありません

$ readelf -a Hello.exe
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
$ xxd Hello.exe | head -n1
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............

MZこれは、Microsoft Windowsが静的にリンクされた実行可能ファイルであることを意味します。Windowsのボックスにドロップすると、実行されます(実行されるはずです)。

私がしているwineインストールされていますが、wineWindowsアプリケーションの互換性層である、約5倍限り実行にかかるHello.exeとしてmono、それを直接実行するか、そうではないwineことは、それを実行します。

syscall / s をインターセプトする、またはで始まるバイナリをキャッチするmonoカーネルモジュールがインストールされてmonoいるが、友人がエラーを返すと仮定しています。exec4D 5Alsmod | grep mono

ここで何が起こっているのでしょうか?また、カーネルはこの実行可能ファイルが特別であることをどのように知ってますか?


証明のためにそれは私のシェルの魔法ではないので、私はそれを実行するためにCrap Shell(別名sh)を使用しましたが、それはネイティブに実行されます。


コメンターが好奇心was盛だったので、ここに完全なプログラムがあります:

using System;

class Hello {
  /// <summary>
  ///   The main entry point for the application
  /// </summary>
  [STAThread]
  public static void Main(string[] args) {
    System.Console.Write("Hello, World!\n");
  }
}

4
あなたは答えを得た、しかし、あなたのようなコマンドを実行すると、私は、少し混乱していますがphp hello.phpまたはpython hello.pyまたはperl hello.plJavaのようなコンパイル言語の場合、またはjava hello、彼らはまた、そこには、実行が、読み出されたプログラムが自分でないように実行し、ファイルを実行しますが。しかし、./hello.exe代わりに実行した場合mono hello.exe、私はあなたの質問を見つけて、より合理的な回答を受け入れました(この場合は間違いなくbinfmt-supportを使用します。
kuldeep.kamboj16年

@ kuldeep.kambojあなたが言っていることを理解しているかはわかりませんが、LinuxボックスでWindows実行可能ファイルが「ネイティブに」実行されることに驚いただけです。

1
実際、私が言っていたことは、コードファイル(またはコンパイルされたファイル)はその形式のプログラムを介して実行できprogram codefile、あなたの場合はプログラムはモノですが、私の例にはphp、python、perl、javaが含まれています。モノがコードを介して実行される.exeファイル以外の拡張子を許可するかどうかは疑わしい。最終的にこれはコンパイルされたコードを実行するため、ウィンドウにまったく依存するべきではありません。ただし、ソースファイルにWindows専用APIなどの依存コードが含まれている場合は、そのexeファイルを実行するために明らかにwineが必要です。
kuldeep.kamboj

4
これの素晴らしい皮肉の一部は、 /etc/magicまたは/usr/share/file/magic(または同様の魔法の場所)これを行うために必要な情報を含むファイルです。

1
@catは非常に興味深いファイルです(お気に入りのファイルを作成する場合、おそらく最初の選択肢になります)。あらゆる種類のファイルを識別するための情報があります。ただし、実行方法を理解する前に、ファイルが最初に何であるかを識別する必要があります。それがファイルとその魔法のすることです。同様のこと- しばらく前からLinux向けのJavaバイナリカーネルをサポートしているので、$ foo.jarむしろ可能です$ java -jar foo.jar-モノの場合と同様です。

回答:


183

これはbinfmt_miscの動作です。これにより、カーネルに、知らないバイナリを実行する方法を伝えることができます。の内容を見てください/proc/sys/fs/binfmt_misc。そこにあるファイルの中で、Monoバイナリの実行方法を説明する必要があります。

enabled
interpreter /usr/lib/binfmt-support/run-detectors
flags:
offset 0
magic 4d5a

(Debianシステム上)。これはカーネルにMZ4d5a)で始まるバイナリを与えるべきことを伝えrun-detectorsます。後者は、Monoを使用するかWineを使用してバイナリを実行するかを決定します。

バイナリタイプはいつでも追加、削除、有効化、無効化できます。詳細については、上記のドキュメントを参照してください(セマンティクスは驚くべきものであり、ここで使用される仮想ファイルシステムは標準ファイルシステムのように完全に動作するわけではありません)。/proc/sys/fs/binfmt_misc/statusグローバルステータスを提供し、各バイナリ「記述子」は個々のステータスを示します。無効にする別の方法はbinfmt_misc、カーネルモジュールがモジュールとしてビルドされている場合、そのカーネルモジュールをアンロードすることです。これは、完全に回避するためにブラックリストに登録することもできることを意味します。

この機能により、MZ実行可能ファイル(Windows PEおよびPE +バイナリ、DOSおよびOS / 2バイナリも含む!)、Java JARファイルなどの新しいバイナリタイプをサポートできます。また、既知のバイナリタイプをサポートすることもできます。通常Qemuを使用する新しいアーキテクチャ。したがって、適切なライブラリを使用すると、IntelプロセッサでARM Linuxバイナリを透過的に実行できます。

あなたの質問は、.NETの意味ではありますが、クロスコンパイルに由来し、警告がbinfmt_miscあります。クロスコンパイルされたバイナリを実行できるシステムでクロスコンパイルしようとすると、いくつかの構成スクリプトが誤動作します。通常、クロスコンパイルを検出するには、バイナリをビルドして実行しようとします。実行する場合、クロスコンパイルしません。実行しない場合、あなたは(またはコンパイラが壊れています)。autoconfこの場合、ビルドおよびホストアーキテクチャを明示的に指定することにより、通常スクリプトを修正できますが、binfmt_misc一時的に無効にする必要がある場合があります...


2
/ procに興味がある人には、/ proc / *の仕組みに興味があるかもしれません。上のスーパーユーザー
CVn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.