Estoy aprendiendo C #, así que hice un pequeño programa de C # que dice Hello, World!
, luego lo compilé mono-csc
y lo ejecuté con mono
:
$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!
Me di cuenta de que cuando me golpeó TAB
en bash
, Hello.exe
fue marcado como ejecutable. De hecho, se ejecuta solo con un shell que carga el nombre del archivo.
Hello.exe
no es un archivo ELF con una extensión de archivo divertida:
$ 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
significa que es un ejecutable enlazado estáticamente de Microsoft Windows. Suéltelo en un cuadro de Windows y se ejecutará (debería).
Lo he wine
instalado, pero wine
, al ser una capa de compatibilidad para aplicaciones de Windows, tarda aproximadamente 5 veces más en ejecutarse Hello.exe
que mono
ejecutarlo directamente, por lo wine
que no es que lo ejecute.
Supongo que hay algún mono
módulo de kernel instalado mono
que intercepta exec
syscall / s, o atrapa binarios que comienzan con 4D 5A
, pero lsmod | grep mono
y los amigos devuelven un error.
¿Qué está pasando aquí y cómo sabe el núcleo que este ejecutable es especial?
Solo como prueba de que no es mi magia de shell, utilicé Crap Shell (aka sh
) para ejecutarlo y todavía se ejecuta de forma nativa.
Aquí está el programa completo, ya que un comentarista tenía curiosidad:
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
opython hello.py
operl hello.pl
o en caso de lenguaje compilado como Javajava hello
también se ejecutan como su son no ejecutable allí, pero un programa de lectura y ejecución de archivos. Sin embargo, si ejecuta en./hello.exe
lugar demono hello.exe
la, encontré su pregunta y acepté la respuesta más razonable (que en caso de que definitivamente use binfmt-support.program codefile
, en su caso, el programa es mono, mientras que mis ejemplos incluyen php, python, perl y java. Sospecho que si mono permite la extensión a otro archivo que no sea .exe aún se ejecuta a través del código. No debería depender en absoluto de Windows, ya que finalmente se ejecuta un código compilado. Sin embargo, si su archivo fuente tiene algún código dependiente, como las API de Windows solamente, entonces obviamente debe necesitar wine para ejecutar ese archivo exe./etc/magic
o/usr/share/file/magic
(o una ubicación mágica similar) es el archivo que contiene la información necesaria para poder hacer esto.$ foo.jar
lugar de hacerlo$ java -jar foo.jar
, similar a lo que se hace para mono.Respuestas:
Esto es binfmt_misc en acción: permite que se le diga al núcleo cómo ejecutar binarios que no conoce. Mira el contenido de
/proc/sys/fs/binfmt_misc
; Entre los archivos que ve allí, uno debe explicar cómo ejecutar mono binarios:(en un sistema Debian). Esto le dice al núcleo que los binarios que comienzan con
MZ
(4d5a
) deben ser dados arun-detectors
. Este último determina si usar Mono o Wine para ejecutar el binario.Los tipos binarios se pueden agregar, eliminar, habilitar y deshabilitar en cualquier momento; Consulte la documentación anterior para obtener más detalles (la semántica es sorprendente, el sistema de archivos virtual utilizado aquí no se comporta completamente como un sistema de archivos estándar).
/proc/sys/fs/binfmt_misc/status
da el estado global, y cada "descriptor" binario muestra su estado individual. Otra forma de deshabilitarbinfmt_misc
es descargar su módulo del núcleo, si está construido como un módulo; Esto también significa que es posible ponerlo en la lista negra para evitarlo por completo.Esta característica permite que se admitan nuevos tipos binarios, como ejecutables MZ (que incluyen binarios de Windows PE y PE +, pero también binarios de DOS y OS / 2), archivos Java JAR ... También permite que se admitan tipos binarios conocidos en nuevas arquitecturas, típicamente usando Qemu; por lo tanto, con las bibliotecas apropiadas, puede ejecutar de forma transparente los binarios ARM Linux en un procesador Intel.
Su pregunta surgió de la compilación cruzada, aunque en el sentido .NET, y eso plantea una advertencia con
binfmt_misc
: algunos scripts de configuración se comportan mal cuando intenta compilar en un sistema que puede ejecutar los binarios con compilación cruzada. Normalmente, detectar la compilación cruzada implica construir un binario e intentar ejecutarlo; si se ejecuta, no estás compilando de forma cruzada, si no lo hace, lo estás (o tu compilador está roto).autoconf
Los scripts generalmente se pueden arreglar en este caso especificando explícitamente las arquitecturas de compilación y host, pero a veces tendrá que deshabilitarbinfmt_misc
temporalmente ...fuente