Uczę się języka C #, więc stworzyłem mały program w języku C #, który mówi Hello, World!
, a następnie skompilowałem go mono-csc
i uruchomiłem z mono
:
$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!
Zauważyłem, że kiedy uderzy TAB
w bash
, Hello.exe
cechował wykonywalny. Rzeczywiście, działa tylko przez powłokę ładującą nazwę pliku!
Hello.exe
to nie jest plik ELF z zabawnym rozszerzenie pliku:
$ 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
oznacza, że jest to plik wykonywalny połączony statycznie z Microsoft Windows. Upuść go w oknie systemu Windows i będzie (powinien) działać.
Mam wine
zainstalowany, ale wine
będąc warstwa kompatybilności z aplikacjami Windows trwa około 5x tak długo, aby uruchomić Hello.exe
jak mono
i wykonywanie go bezpośrednio nie, więc nie jest to wine
, że prowadzi go.
Zakładam, że jest mono
zainstalowany moduł jądra, mono
który przechwytuje exec
syscall / s lub przechwytuje pliki binarne, które zaczynają się od 4D 5A
, ale lsmod | grep mono
znajomi zwracają błąd.
Co się tutaj dzieje i skąd jądro wie, że ten plik wykonywalny jest wyjątkowy?
Na dowód, że to nie moja magia działająca w powłoce, użyłem Crap Shell (aka sh
), aby ją uruchomić i nadal działa natywnie.
Oto pełny program, ponieważ komentator był ciekawy:
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
lubpython hello.py
lubperl hello.pl
lub w przypadku skompilowanego języka takiego jak javajava hello
, uruchomiliby się również, ponieważ nie są tam wykonywalne, ale program odczytuje i wykonuje plik. Jeśli jednak uruchomisz./hello.exe
zamiastmono hello.exe
, znalazłem twoje pytanie i zaakceptowałem bardziej sensowną odpowiedź (która w przypadku zdecydowanie skorzysta z obsługi binfmt.program codefile
, w twoim przypadku program jest mono, podczas gdy moje przykłady obejmują php, python, perl i java. Podejrzewam, czy mono zezwala na rozszerzenie pliku innego niż .exe nadal wykonywanego za pomocą kodu. Nie powinno to wcale zależeć od systemu Windows, ponieważ w końcu jest to wykonywany skompilowany kod. Jednak jeśli plik źródłowy ma jakiś kod zależny, taki jak interfejsy API systemu Windows, to oczywiście potrzebujesz wina do uruchomienia tego pliku exe./etc/magic
lub/usr/share/file/magic
(lub podobna magiczna lokalizacja) to plik zawierający informacje niezbędne do tego, aby to zrobić.$ foo.jar
zamiast$ java -jar foo.jar
- podobnie jak w przypadku mono.Odpowiedzi:
To jest binfmt_misc w akcji: pozwala jądrze dowiedzieć się, jak uruchomić pliki binarne, o których nie wie. Spójrz na zawartość
/proc/sys/fs/binfmt_misc
; wśród plików, które tam widzisz, należy wyjaśnić, jak uruchomić pliki binarne Mono:(w systemie Debian). To informuje jądro, że należy podać pliki binarne zaczynające się od
MZ
(4d5a
)run-detectors
. Ten ostatni zastanawia się, czy użyć Mono czy Wine do uruchomienia pliku binarnego.Typy binarne można dodawać, usuwać, włączać i wyłączać w dowolnym momencie; zobacz szczegóły w powyższej dokumentacji (semantyka jest zaskakująca, stosowany tutaj wirtualny system plików nie zachowuje się całkowicie jak standardowy system plików).
/proc/sys/fs/binfmt_misc/status
podaje status globalny, a każdy binarny „deskryptor” pokazuje swój indywidualny status. Innym sposobem wyłączeniabinfmt_misc
jest zwolnienie modułu jądra, jeśli jest on zbudowany jako moduł; oznacza to również, że można go umieścić na czarnej liście, aby całkowicie tego uniknąć.Ta funkcja umożliwia obsługę nowych typów plików binarnych, takich jak pliki wykonywalne MZ (które obejmują pliki binarne Windows PE i PE +, ale także pliki binarne DOS i OS / 2!), Pliki Java JAR ... Umożliwia także obsługę znanych typów binarnych na nowe architektury, zwykle wykorzystujące Qemu; dzięki odpowiednim bibliotekom możesz transparentnie uruchamiać binaria ARM Linux na procesorze Intel!
Twoje pytanie wynikało z kompilacji krzyżowej, choć w sensie .NET, i to wywołuje zastrzeżenie
binfmt_misc
: niektóre skrypty konfiguracyjne źle zachowują się podczas próby kompilacji krzyżowej w systemie, który może uruchamiać binaria kompilowane krzyżowo. Zazwyczaj wykrywanie kompilacji krzyżowej wymaga zbudowania pliku binarnego i próby jego uruchomienia; jeśli to działa, nie kompilujesz się, a jeśli nie, jesteś (lub twój kompilator jest zepsuty).autoconf
w tym przypadku skrypty można zwykle naprawić, wyraźnie określając architekturę kompilacji i hosta, ale czasami trzebabinfmt_misc
tymczasowo wyłączyć ...źródło