
Acabo de descubrir algo realmente sorprendente.
Puedo compilar un simple C# hola mundo en mi computadora con Windows usando csc
(desde Visual Studio), copiar el exe
archivo resultante a mi computadora con Linux y ejecutarlo con mono helloworld.exe
. Hasta ahora todo tiene sentido para mí: segúnesta publicación SO, en Windows, helloworld.exe
es básicamente solo un truco que termina iniciando el tiempo de ejecución de C#, y el código de bytes CIL simplemente se lee de alguna sección de datos más adelante en el exe
archivo. Del mismo modo, me imagino que, en Linux, mono helloworld.exe
simplemente inicia el tiempo de ejecución de C# y lee directamente el código de bytes sin molestarse con el truco del exe.
Para la posteridad, aquí está la fuente, que obtuve deExcelente libro gratuito sobre C# de Charles Petzold:
//---------------------------------------------
// FirstProgram.cs (c) 2006 by Charles Petzold
//---------------------------------------------
class FirstProgram
{
public static void Main()
{
System.Console.WriteLine("Hello, Microsoft .NET Framework!");
}
}
Pero aquí es donde las cosas se ponen interesantes: en Linux ( uname -r
en mi máquina da 4.14.188-1-MANJARO
), simplemente puedo hacerlo ./helloworld.exe
y ¡funciona!
Empecé a investigar un poco y aquí están las primeras líneas de la ejecución 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)
Habría esperado algún error que dijera "este archivo no es un ejecutable válido", ya que solo espero que el cargador de programas de Linux comprenda los archivos ELF en lugar del formato PE de Windows. En cambio, parece que de alguna manera el sistema es lo suficientemente inteligente como para comenzar a buscar Wine (en el strace
resultado, puedes ver que comienza a buscar bibliotecas de Wine, y como instalé Wine en mi máquina Linux, finalmente las encuentra más tarde). en).
Entonces, ¿qué está pasando? ¿Es la execve
llamada lo suficientemente inteligente como para intentar usar Wine si detecta un archivo PE, o es algo que bash
está haciendo? ¿O es algo completamente diferente?
Respuesta1
Definitivamente tiene Wine o Mono instalado a través de un administrador de paquetes y junto con él un archivo de configuración especial que le dice al kernel qué hacer una vez que el usuario inicia un archivo exe.
Más sobre esto aquí:https://en.wikipedia.org/wiki/Binfmt_misc