Bagaimana Mono ajaib?

149

Saya sedang belajar C #, jadi saya membuat program C # kecil yang mengatakan Hello, World!, lalu mengompilasinya mono-cscdan menjalankannya dengan mono:

$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!

Saya menyadari bahwa ketika saya memukul TABdi bash, Hello.exeditandai dieksekusi. Memang, ini dijalankan hanya dengan sebuah shell memuat nama file!

Hello.exeadalah tidak file ELF dengan ekstensi file yang lucu:

$ 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..............

MZberarti itu adalah Microsoft Windows yang dapat dieksekusi yang terhubung secara statis. Jatuhkan ke kotak Windows, dan itu akan (harus) berjalan.

Saya telah wineterinstal, tapi wine, menjadi lapisan kompatibilitas untuk aplikasi Windows, membutuhkan waktu sekitar 5x lebih lama untuk menjalankan Hello.exesebagai monodan dijalankan langsung lakukan, sehingga tidak wineyang berjalan itu.

Saya berasumsi ada beberapa monomodul kernel yang diinstal dengan monoyang mencegat execsyscall / s, atau menangkap binari yang dimulai dengan 4D 5A, tetapi lsmod | grep monodan teman-teman mengembalikan kesalahan.

Apa yang terjadi di sini, dan bagaimana kernel tahu bahwa ini executable khusus?


Hanya untuk membuktikan itu bukan sihir shell saya , saya menggunakan Crap Shell (alias sh) untuk menjalankannya dan masih berjalan secara asli.


Inilah programnya secara penuh, karena seorang komentator ingin tahu:

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");
  }
}
kucing
sumber
4
Ketika Anda mendapat jawaban, Tapi saya agak bingung, Jika Anda menjalankan perintah seperti php hello.phpatau python hello.pyatau perl hello.pljika bahasa dikompilasi seperti java java hellomereka juga akan berjalan karena mereka tidak dapat dieksekusi di sana tetapi sebuah program membaca dan mengeksekusi file. Namun jika Anda menjalankan ./hello.exealih-alih mono hello.exe, saya menemukan pertanyaan Anda dan menerima jawaban yang lebih masuk akal (yang dalam kasus pasti menggunakan dukungan
binfmt
@ kuldeep.kamboj Saya tidak yakin saya mengerti apa yang Anda katakan tetapi saya hanya terkejut bahwa executable Windows berjalan "secara native" pada kotak Linux.
kucing
1
Sebenarnya apa yang saya katakan bahwa file kode apa pun (atau file yang dikompilasi) dapat dieksekusi melalui programnya dalam format program codefile, dalam program kasus Anda adalah mono, sedangkan contoh saya termasuk php, python, perl dan java. Saya curiga jika mono mengizinkan ekstensi selain file .exe masih dieksekusi melalui kode. Seharusnya tidak bergantung sama sekali pada windows karena akhirnya ini menjalankan kode yang dikompilasi. Namun jika file sumber Anda memiliki beberapa kode dependen seperti windows only API maka jelas Anda harus memerlukan anggur untuk menjalankan file exe itu.
kuldeep.kamboj
4
Bagian dari ironi yang indah dari hal ini adalah bahwa /etc/magicatau /usr/share/file/magic(atau lokasi magis serupa) adalah file yang berisi informasi yang diperlukan untuk dapat melakukan ini.
1
@cat ini file yang sangat menarik (jika saya memiliki file favorit, itu mungkin akan menjadi pilihan pertama saya). Ini memiliki informasi untuk mengidentifikasi semua jenis file. Tetapi Anda perlu mengidentifikasi apa file itu terlebih dahulu sebelum Anda tahu cara menjalankannya. Itulah yang dilakukan file dan keajaibannya. Hal serupa - Dukungan Java Binary Kernel untuk Linux dari beberapa waktu sehingga Anda dapat melakukan $ foo.jardaripada $ java -jar foo.jar- mirip dengan apa yang dilakukan untuk mono.

Jawaban:

183

Ini adalah binfmt_misc yang sedang beraksi: memungkinkan kernel untuk diberi tahu bagaimana menjalankan binari yang tidak diketahuinya. Lihatlah isi /proc/sys/fs/binfmt_misc; di antara file yang Anda lihat di sana, orang harus menjelaskan cara menjalankan binari Mono:

enabled
interpreter /usr/lib/binfmt-support/run-detectors
flags:
offset 0
magic 4d5a

(pada sistem Debian). Ini memberi tahu kernel tempat binari dimulai dengan MZ( 4d5a) harus diberikan run-detectors. Yang terakhir mengetahui apakah menggunakan Mono atau Wine untuk menjalankan biner.

Jenis biner dapat ditambahkan, dihapus, diaktifkan dan dinonaktifkan kapan saja; lihat dokumentasi di atas untuk perincian (semantiknya mengejutkan, sistem file virtual yang digunakan di sini tidak berperilaku sepenuhnya seperti sistem file standar). /proc/sys/fs/binfmt_misc/statusmemberikan status global, dan masing-masing "deskriptor" biner menunjukkan status masing-masing. Cara lain untuk menonaktifkan binfmt_miscadalah membongkar modul kernelnya, jika itu dibangun sebagai modul; ini juga berarti memungkinkan untuk masuk daftar hitam untuk menghindarinya sepenuhnya.

Fitur ini memungkinkan tipe biner baru untuk didukung, seperti executable MZ (yang termasuk Windows PE dan PE + binari, tetapi juga DOS dan OS / 2 binari!), File Java JAR ... Ini juga memungkinkan tipe biner yang dikenal untuk didukung pada arsitektur baru, biasanya menggunakan Qemu; dengan demikian, dengan perpustakaan yang sesuai, Anda dapat menjalankan binari ARM Linux secara transparan pada prosesor Intel!

Pertanyaan Anda berasal dari kompilasi silang, meskipun dalam arti .NET, dan itu menimbulkan peringatan dengan binfmt_misc: beberapa skrip konfigurasi keliru ketika Anda mencoba melakukan cross-compile pada sistem yang dapat menjalankan binari cross-compiled. Biasanya, mendeteksi kompilasi silang melibatkan membangun biner dan mencoba menjalankannya; jika berjalan, Anda tidak kompilasi silang, jika tidak, Anda (atau kompiler Anda rusak). autoconfskrip biasanya dapat diperbaiki dalam hal ini dengan secara eksplisit menentukan arsitektur build dan host, tetapi kadang-kadang Anda harus menonaktifkan binfmt_miscsementara ...

Stephen Kitt
sumber
2
Bagi mereka yang ingin tahu tentang / proc, Anda mungkin tertarik pada Bagaimana cara / proc / * bekerja? pada Pengguna Super .
CVn