
Ich habe gerade etwas wirklich Überraschendes entdeckt.
csc
Ich kann auf meinem Windows-Computer mit (aus Visual Studio) eine einfache C#-Hello-World-Datei kompilieren , die resultierende exe
Datei auf meinen Linux-Computer kopieren und mit ausführen mono helloworld.exe
. Bis jetzt macht für mich alles Sinn: Lautdieser SO-Beitragist unter Windows helloworld.exe
im Grunde nur ein Trick, der die C#-Runtime startet und den CIL-Bytecode einfach aus einem Datenabschnitt weiter unten in der exe
Datei liest. Ebenso stelle ich mir vor, dass unter Linux mono helloworld.exe
einfach die C#-Runtime gestartet und der Bytecode direkt gelesen wird, ohne sich mit dem EXE-Trick herumzuschlagen.
Für die Nachwelt hier die Quelle, die ich vonCharles Petzolds ausgezeichnetes kostenloses C#-Buch:
//---------------------------------------------
// FirstProgram.cs (c) 2006 by Charles Petzold
//---------------------------------------------
class FirstProgram
{
public static void Main()
{
System.Console.WriteLine("Hello, Microsoft .NET Framework!");
}
}
Aber hier wird es interessant: Unter Linux (das uname -r
auf meinem Rechner verfügbar ist 4.14.188-1-MANJARO
) kann ich das einfach tun ./helloworld.exe
und es funktioniert!
Ich begann, ein wenig nachzuforschen, und hier sind die ersten paar Zeilen aus „running“ strace ./helloworld.exe
:
execve("./hw.exe", ["./hw.exe"], 0x7fffae8e6070 /* 61 vars */) = 0
[ Process PID=3381 runs in 32 bit mode. ]
brk(NULL) = 0x7eedb000
arch_prctl(0x3001 /* ARCH_??? */, 0xffb19948) = -1 EINVAL (Invalid argument)
readlink("/proc/self/exe", "/usr/bin/wine", 4096) = 13
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7faa000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/i686/sse2/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls/i686/sse2", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/i686/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls/i686", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/sse2/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls/sse2", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/i686/sse2/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/i686/sse2", 0xffb18e00) = -1 ENOENT (No such file or directory)
Ich hätte eine Fehlermeldung erwartet, die besagt, dass diese Datei keine gültige ausführbare Datei ist, da ich nur erwarte, dass der Linux-Programmlader ELF-Dateien und nicht das PE-Format von Windows versteht. Stattdessen scheint das System irgendwie intelligent genug zu sein, um mit der Suche nach Wine zu beginnen (in der strace
Ausgabe können Sie sehen, dass es mit der Suche nach Wine-Bibliotheken beginnt, und da ich Wine auf meinem Linux-Rechner installiert habe, findet es sie später tatsächlich).
Was ist also los? Ist der execve
Aufruf intelligent genug, um Wine zu verwenden, wenn er eine PE-Datei erkennt, oder ist das etwas, das bash
gerade passiert? Oder ist es etwas ganz anderes?
Antwort1
Mit Sicherheit haben Sie entweder Wine und/oder Mono über einen Paketmanager installiert und dazu eine spezielle Konfigurationsdatei, die dem Kernel mitteilt, was zu tun ist, wenn der Benutzer eine EXE-Datei startet.
Mehr dazu hier:https://en.wikipedia.org/wiki/Binfmt_misc