Як Mono магічне?


149

Я вивчаю C #, тому я створив невелику програму C #, яка каже Hello, World!, потім склав її mono-cscі запустив mono:

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

Я помітив , що коли я потрапив TABв bash, Hello.exeбув відзначений виконуваним. Дійсно, він працює лише оболонкою, що завантажує ім'я файлу!

Hello.exeце НЕ файл ELF з кумедним розширенням файлу:

$ 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означає, що це стаціонарно пов'язаний виконуваний файл Microsoft Windows. Перекиньте його на вікно Windows, і воно (повинно) працювати.

Я wineвстановив, але wine, будучи шаром сумісності для додатків для Windows, потрібно запустити приблизно 5 разів стільки часу, Hello.exeяк monoі виконати його безпосередньо, так що це не wineте, що він запускає.

Я припускаю, що monoвстановлено якийсь модуль ядра, monoякий перехоплює execsyscall / s або ловить двійкові файли, які починаються з цього 4D 5A, але lsmod | grep monoдрузі повертають помилку.

Що тут відбувається, і як ядро ​​знає, що цей виконуваний файл є особливим?


Просто на доказ, що це не моя магія, що працює з оболонкою, я використовував Crap Shell (ака sh), щоб запустити її, і вона все ще працює на самому справі.


Ось програма в повному обсязі, оскільки коментатор був цікавим:

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");
  }
}

4
Поки ви отримали відповідь, але я трохи розгублений, якщо ви запускаєте команди на зразок php hello.phpабо python hello.pyабо perl hello.plабо у випадку складеної мови на зразок java, java helloвони також будуть виконуватись, оскільки їх там не виконується, але файл зчитування та виконання програми. Однак якщо ви біжите ./hello.exeзамість mono hello.exeтого, я знайшов ваше запитання та прийняв відповідь більш розумною (що у випадку, коли ви обов'язково використовуєте підтримку binfmt.
kuldeep.kamboj

@ kuldeep.kamboj Я не впевнений, що я розумію, про що ви говорите, але мене просто здивувало, що виконуваний файл Windows працює "споконвічно" у вікні Linux.
кіт

1
Насправді я казав, що будь-який файл коду (або компільований файл) може бути виконаний через його програму у форматі program codefile, у вашому випадку програма є моно, тоді як мої приклади включають php, python, perl та java. Я підозрюю, якщо моно дозволяють розширення на інший, ніж .exe файл, все ще виконується за допомогою коду. Це взагалі не повинно залежати від windows, оскільки нарешті це виконується складеним кодом. Однак якщо у вашому вихідному файлі є якийсь залежний код, наприклад API лише для Windows, тоді, очевидно, для запуску цього EXE-файлу вам знадобиться вино.
kuldeep.kamboj

4
Частина чудової іронії цього полягає в тому, що /etc/magicабо /usr/share/file/magic(або подібне магічне розташування) - це файл, який містить інформацію, необхідну для того, щоб зробити це.

1
@cat - це дуже цікавий файл (якби у мене був улюблений файл, мабуть, це був би мій перший вибір). Він містить інформацію для ідентифікації всіляких файлів. Але вам потрібно визначити, що саме таке файл, перш ніж ви зможете зрозуміти, як його запустити. Ось що робить файл і його магія. Аналогічна річ - підтримка Java Binary Kernel для Linux з деякого часу назад, так що ви могли б зробити, $ foo.jarа не $ java -jar foo.jar- аналогічно тому, що робиться для моно.

Відповіді:


183

Це binfmt_misc в дії: він дозволяє ядру розповідати, як запускати бінарні файли, про які він не знає. Подивіться на зміст /proc/sys/fs/binfmt_misc; серед файлів, які ви бачите там, слід пояснити, як запускати Mono бінарні файли:

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

(у системі Debian). Це вказує на ядро, якому слід надати бінарні файли, що починаються з MZ( 4d5a) run-detectors. Останній визначає, чи слід використовувати Mono або Wine для запуску бінарного файлу.

Бінарні типи можна будь-коли додавати, видаляти, вмикати та вимикати; Детальні відомості див. у документації вище (семантика викликає подив. Віртуальна файлова система, що використовується тут, не веде себе як стандартна файлова система). /proc/sys/fs/binfmt_misc/statusнадає глобальний статус, і кожен двійковий «дескриптор» показує свій індивідуальний статус. Інший спосіб відключення binfmt_misc- вивантажити його модуль ядра, якщо він побудований як модуль; це також означає, що це можливо в чорний список, щоб уникнути цього повністю.

Ця функція дозволяє підтримувати нові бінарні типи, такі як виконувані файли MZ (до яких належать бінарні файли Windows PE та PE +, а також бінарні файли DOS та OS / 2!), Файли Java JAR ... Також дозволяє підтримувати відомі бінарні типи на нові архітектури, зазвичай використовують Qemu; Таким чином, за допомогою відповідних бібліотек ви можете прозоро запускати бінарні файли ARM Linux на процесорі Intel!

Ваше запитання випливало з перехресної компіляції, хоча і в сенсі .NET, і це означає, що binfmt_miscдеякі сценарії конфігурації погано поводяться при спробі крос-компіляції в системі, яка може запускати крос-складені бінарні файли. Як правило, виявлення перехресної компіляції включає побудову двійкового файлу та спробу його запуску; якщо він працює, ви не перетинаєте, якщо цього немає, ви (або ваш компілятор зламаний). autoconfСценарії зазвичай можуть бути виправлені в цьому випадку, чітко вказавши архітектури збірки та хоста, але іноді доведеться binfmt_miscтимчасово відключити ...


2
Для тих, хто цікавиться / proc, вас може зацікавити, як працює / proc / *? на Super User .
CVn
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.