Ich lerne C #, deshalb habe ich ein kleines C # -Programm erstellt, in dem steht, dass ich es Hello, World!
kompiliert mono-csc
und ausgeführt habe mit mono
:
$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!
Ich bemerkte , dass , wenn ich traf TAB
in bash
, Hello.exe
wurde ausführbar markiert. Tatsächlich läuft es nur mit einer Shell, die den Dateinamen lädt!
Hello.exe
ist keine ELF-Datei mit einer lustigen Dateierweiterung:
$ 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
bedeutet, dass es sich um eine statisch verknüpfte ausführbare Datei von Microsoft Windows handelt. Legen Sie es auf einer Windows-Box ab, und es wird (sollte) ausgeführt.
Ich habe wine
installiert, aber wine
eine Kompatibilitätsschicht für Windows - Anwendungen ist, dauert etwa 5 - fach so lange laufen , Hello.exe
wie mono
und Ausführung direkt zu tun, so ist es nicht , wine
dass es läuft.
Ich gehe davon aus, dass ein mono
Kernelmodul installiert ist mono
, das den exec
/ die Syscall / s abfängt oder Binärdateien abfängt , die mit beginnen 4D 5A
, aber lsmod | grep mono
Freunde geben einen Fehler zurück.
Was ist hier los und woher weiß der Kernel, dass diese ausführbare Datei etwas Besonderes ist?
Nur zum Beweis, dass es nicht meine Shell-Arbeitsmagie ist, habe ich die Crap Shell (aka sh
) verwendet, um sie auszuführen, und sie läuft immer noch nativ.
Hier ist das Programm vollständig, da ein Kommentator neugierig war:
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");
}
}
php hello.php
oderpython hello.py
oderperl hello.pl
oder im Falle einer kompilierten Sprache wie Javajava hello
ausführen, werden sie auch ausgeführt, da sie dort keine ausführbare Datei sind, sondern ein Programm zum Lesen und Ausführen einer Datei. Wenn Sie jedoch./hello.exe
anstelle von ausführen,mono hello.exe
fand ich Ihre Frage und akzeptierte Antwort vernünftiger (die auf jeden Fall binfmt-Unterstützung verwenden.program codefile
, in Ihrem Fall ist das Programm mono, während meine Beispiele PHP, Python, Perl und Java enthalten. Ich vermute, wenn Mono die Erweiterung auf eine andere als die EXE-Datei zulässt, die immer noch über Code ausgeführt wird. Es sollte überhaupt nicht von Windows abhängen, da letztendlich ein kompilierter Code ausgeführt wird. Wenn Ihre Quelldatei jedoch einen abhängigen Code hat, wie z. B. nur Windows-APIs, müssen Sie Wein zum Ausführen dieser Exe-Datei benötigen./etc/magic
oder/usr/share/file/magic
(oder ein ähnlicher magischer Ort) die Datei enthält, die die Informationen enthält, die erforderlich sind, um dies zu tun.$ foo.jar
eher tun könnten als$ java -jar foo.jar
- ähnlich wie bei Mono.Antworten:
Dies ist binfmt_misc in Aktion: Hiermit kann der Kernel erfahren, wie er unbekannte Binärdateien ausführt. Schauen Sie sich den Inhalt von an
/proc/sys/fs/binfmt_misc
. Unter den dort angezeigten Dateien sollte erklärt werden, wie Mono-Binärdateien ausgeführt werden:(auf einem Debian-System). Dies teilt dem Kernel mit, dass Binärdateien, die mit
MZ
(4d5a
) beginnen, übergeben werden sollenrun-detectors
. Letzteres ermittelt, ob Mono oder Wine zum Ausführen der Binärdatei verwendet werden soll.Binärtypen können jederzeit hinzugefügt, entfernt, aktiviert und deaktiviert werden. Einzelheiten finden Sie in der Dokumentation oben (die Semantik ist überraschend, das hier verwendete virtuelle Dateisystem verhält sich nicht ganz wie ein Standard-Dateisystem).
/proc/sys/fs/binfmt_misc/status
gibt den globalen Status an und jeder binäre "Deskriptor" zeigt seinen individuellen Status an. Eine andere Möglichkeit zum Deaktivierenbinfmt_misc
besteht darin, das Kernelmodul zu entladen, wenn es als Modul erstellt wurde. Dies bedeutet auch, dass es möglich ist, eine schwarze Liste zu erstellen, um dies vollständig zu vermeiden.Mit dieser Funktion können neue Binärtypen unterstützt werden, z. B. ausführbare MZ-Dateien (einschließlich Windows PE- und PE + -Binärdateien, aber auch DOS- und OS / 2-Binärdateien!), Java-JAR-Dateien. Außerdem können bekannte Binärtypen unterstützt werden neue Architekturen, typischerweise mit Qemu; Auf diese Weise können Sie mit den entsprechenden Bibliotheken ARM Linux-Binärdateien auf einem Intel-Prozessor transparent ausführen!
Ihre Frage ergab sich aus der Cross-Kompilierung, wenn auch im .NET-Sinne, und führt zu einer Einschränkung
binfmt_misc
: Einige Konfigurationsskripte verhalten sich falsch, wenn Sie versuchen, eine Cross-Kompilierung auf einem System durchzuführen, auf dem die cross-kompilierten Binärdateien ausgeführt werden können. In der Regel müssen Sie zum Erkennen einer Kreuzkompilierung eine Binärdatei erstellen und versuchen, diese auszuführen. Wenn es läuft, werden Sie nicht überkompiliert. Wenn es nicht läuft, sind Sie (oder Ihr Compiler ist kaputt).autoconf
Skripte können in diesem Fall normalerweise durch explizite Angabe der Build- und Host-Architektur behoben werden. Manchmal müssen Sie sie jedochbinfmt_misc
vorübergehend deaktivieren .quelle