单声道魔术如何?


149

我正在学习C#,所以我制作了一个小C#程序,说Hello, World!,然后使用进行编译mono-csc并运行mono

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

我注意到,当我点击TABbashHello.exe被标记为可执行。确实,它只是通过加载文件名的shell运行!

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.exemono,并执行它直接做的,所以它不是wine运行它。

我假设mono安装了一些内核模块,mono该模块可以拦截execsyscall / s或捕获以开头的二进制文件4D 5A,但是lsmod | grep mono朋友返回错误。

这是怎么回事,内核如何知道可执行文件很特殊?


只是为了证明这不是我的 shell魔术,我使用了Crap Shell(aka 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.phpor或python hello.pyor perl hello.pl或在Java之类的编译语言的情况下,java hello它们也将运行,因为它们在那里不是可执行文件,而是程序读取并执行文件。然而,如果你运行./hello.exe的,而不是mono hello.exe在我发现你的问题,接受的答案更合理(这在一定情况下使用binfmt支持。
kuldeep.kamboj

@ kuldeep.kamboj我不确定我是否理解您的意思,但是我很惊讶Windows可执行文件在Linux机器上“本地”运行。

1
实际上,我所说的是,任何代码文件(或编译文件)都可以通过格式为的程序通过其程序执行program codefile,在您的情况下,程序为mono,而我的示例包括php,python,perl和java。我怀疑单声道是否允许通过.exe文件扩展到.exe文件以外的文件。它不应完全依赖于Windows,因为这最终是执行已编译的代码。但是,如果源文件具有某些依赖代码,例如仅Windows API,那么显然您必须需要wine才能运行该exe文件。
kuldeep.kamboj 2016年

4
具有讽刺意味的是,“ /etc/magic或” /usr/share/file/magic(或类似的魔术位置)是包含能够执行此操作所需信息的文件。

1
@cat是一个非常有趣的文件(如果我要收藏一个文件,那可能是我的首选)。它具有识别各种文件的信息。但是,在确定如何运行文件之前,您需要先确定文件是什么。这就是文件及其作用所在。类似的事情- 不久前对Linux的Java Binary Kernel支持使您可以做$ foo.jar而不是$ java -jar foo.jar-与mono相似。

Answers:


183

这就是binfmt_misc的作用:它允许内核被告知如何运行未知的二进制文件。看一下内容/proc/sys/fs/binfmt_misc;在您看到的文件中,应该解释一下如何运行Mono二进制文件:

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

(在Debian系统上)。这告诉内核,应将以MZ4d5a)开头的二进制文件赋予run-detectors。后者指出是使用Mono还是Wine来运行二进制文件。

二进制类型可以随时添加,删除,启用和禁用。有关详细信息,请参见上面的文档(语义令人惊讶,此处使用的虚拟文件系统的行为并不完全类似于标准文件系统)。/proc/sys/fs/binfmt_misc/status给出全局状态,每个二进制“描述符”显示其各自的状态。另一种禁用方法binfmt_misc是卸载其内核模块(如果它是作为模块构建的)。这也意味着可以将其列入黑名单,从而完全避免使用它。

此功能允许支持新的二进制类型,例如MZ可执行文件(其中包括Windows PE和PE +二进制文件,还包括DOS和OS / 2二进制文件!),Java JAR文件...它还允许在以下位置支持已知的二进制类型:新架构,通常使用Qemu;因此,使用适当的库,您可以在Intel处理器上透明地运行ARM Linux二进制文件!

您的问题源于交叉编译(尽管在.NET方面),但提出了以下警告binfmt_misc:当您尝试在可以运行交叉编译的二进制文件的系统上交叉编译时,某些配置脚本行为不当。通常,检测交叉编译涉及构建二进制文件并尝试运行它。如果运行,则您不会交叉编译,否则,您就交叉编译了(或编译器坏了)。autoconf在这种情况下,通常可以通过显式指定构建和宿主体系结构来修复脚本,但有时您必须binfmt_misc暂时禁用它。


2
对于那些对/ proc感兴趣的人,您可能会对/ proc / *的工作方式感兴趣超级用户上
CVn
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.