Estou aprendendo c #, então fiz um pequeno programa em c # que diz Hello, World!
, compilei mono-csc
e executei com mono
:
$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!
Notei que quando eu bati TAB
em bash
, Hello.exe
foi marcado executável. Na verdade, ele roda apenas por um shell que carrega o nome do arquivo!
Hello.exe
não é um arquivo ELF com uma extensão de arquivo engraçada:
$ 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 é um executável estaticamente vinculado do Microsoft Windows. Solte-o em uma caixa do Windows e ele (deve) ser executado.
Tenho wine
instalado, mas wine
, sendo uma camada de compatibilidade para aplicativos Windows, leva cerca de 5x mais tempo para executar Hello.exe
como mono
e executá-lo diretamente que, portanto, não é wine
que vai.
Eu estou assumindo que há algum mono
módulo do kernel instalado com mono
que intercepta o exec
syscall / s ou captura binários que começam com 4D 5A
, mas os lsmod | grep mono
amigos retornam um erro.
O que está acontecendo aqui e como o kernel sabe que esse executável é especial?
Só para provar que não é a minha mágica de trabalho do shell, usei o Crap Shell (aka sh
) para executá-lo e ele ainda é executado de forma nativa.
Aqui está o programa na íntegra, uma vez que um comentarista estava curioso:
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
oupython hello.py
ouperl hello.pl
ou no caso de linguagem compilada como java,java hello
eles também serão executados, pois não são executáveis lá, mas um programa lê e executa o arquivo. No entanto, se você executar./hello.exe
em vezmono hello.exe
do que eu encontrei sua pergunta e resposta aceita mais razoável (que no caso definitivamente usar binfmt-apoio.program codefile
, no seu caso o programa é mono, enquanto meus exemplos incluem php, python, perl e java. Eu suspeito que se mono permitir extensão para outro arquivo que não seja .exe ainda executado via código. Não deve depender absolutamente do Windows, pois, finalmente, este é um código compilado. No entanto, se o seu arquivo de origem tiver algum código dependente, como APIs apenas do Windows, obviamente você precisará do wine para executar esse arquivo exe./etc/magic
ou/usr/share/file/magic
(ou local mágico semelhante) é o arquivo que contém as informações necessárias para poder fazer isso.$ foo.jar
pouco do que$ java -jar foo.jar
- semelhante ao que é feito para mono.Respostas:
Isso é binfmt_misc em ação: permite que o kernel seja informado sobre como executar binários que não conhece. Veja o conteúdo de
/proc/sys/fs/binfmt_misc
; Entre os arquivos que você vê lá, deve-se explicar como executar os binários Mono:(em um sistema Debian). Isso informa ao kernel que os binários iniciados com
MZ
(4d5a
) devem ser fornecidosrun-detectors
. O último calcula se o Mono ou o Wine deve ser executado para executar o binário.Tipos binários podem ser adicionados, removidos, ativados e desativados a qualquer momento; veja a documentação acima para obter detalhes (a semântica é surpreendente, o sistema de arquivos virtual usado aqui não se comporta inteiramente como um sistema de arquivos padrão).
/proc/sys/fs/binfmt_misc/status
fornece o status global e cada "descritor" binário mostra seu status individual. Outra maneira de desativarbinfmt_misc
é descarregar seu módulo do kernel, se ele for construído como um módulo; isso também significa que é possível colocá-lo na lista negra para evitá-lo completamente.Esse recurso permite que novos tipos binários sejam suportados, como executáveis MZ (que incluem binários Windows PE e PE +, mas também binários DOS e OS / 2!), Arquivos Java JAR ... Também permite que tipos binários conhecidos sejam suportados em novas arquiteturas, normalmente usando o Qemu; portanto, com as bibliotecas apropriadas, você pode executar de forma transparente os binários do ARM Linux em um processador Intel!
Sua pergunta surgiu da compilação cruzada, embora no sentido .NET, e isso traz uma ressalva
binfmt_misc
: alguns scripts de configuração se comportam mal quando você tenta compilar em um sistema que pode executar os binários compilados. Normalmente, a detecção da compilação cruzada envolve a construção de um binário e a tentativa de executá-lo; se for executado, você não fará a compilação cruzada; caso contrário, estará (ou o seu compilador está quebrado).autoconf
Geralmente, os scripts podem ser corrigidos nesse caso, especificando explicitamente as arquiteturas de compilação e host, mas às vezes você precisará desativarbinfmt_misc
temporariamente ...fonte