Mono到底有多神奇?

cat*_*cat 156 linux mono executable cross-compilation

我正在学习 C#,所以我做了一个 C# 小程序,上面写着Hello, World!,然后用以下命令编译mono-csc并运行它mono

$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!
Run Code Online (Sandbox Code Playgroud)

我注意到当我TAB输入bash,Hello.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..............
Run Code Online (Sandbox Code Playgroud)

MZ意味着它是 Microsoft Windows 静态链接的可执行文件。把它放到一个 Windows 盒子上,它就会(应该)运行。

我已经wine安装了,但是wine,是用于的Windows应用程序的兼容层,需时约5倍,只要运行Hello.exemono,并执行它直接做的,所以这并不是wine说运行它。

我假设mono安装了一些内核模块mono来拦截exec系统调用/s,或者捕获以 开头的二进制文件4D 5A,但是lsmod | grep mono朋友们返回一个错误。

这里发生了什么,内核如何知道这个可执行文件是特殊的?


只是为了证明这不是我的shell 工作魔法,我使用了 Crap Shell(又名sh)来运行它,它仍然在本地运行。


这是完整的程序,因为评论者很好奇:

$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!
Run Code Online (Sandbox Code Playgroud)

Ste*_*itt 194

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

enabled
interpreter /usr/lib/binfmt-support/run-detectors
flags:
offset 0
magic 4d5a
Run Code Online (Sandbox Code Playgroud)

(在 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;因此,使用适当的库,您可以在 Intel 处理器上透明地运行 ARM Linux 二进制文件!

您的问题源于交叉编译,尽管是在 .NET 意义上,这带来了一个警告binfmt_misc:当您尝试在可以运行交叉编译的二进制文件的系统上进行交叉编译时,某些配置脚本行为不端。通常,检测交叉编译涉及构建二进制文件并尝试运行它;如果它运行,你没有交叉编译,如果没有,你是(或者你的编译器坏了)。autoconf在这种情况下,通常可以通过明确指定构建和主机架构来修复脚本,但有时您必须binfmt_misc暂时禁用...

  • 对于那些对 /proc 感到好奇的人,您可能对 [su] 上的 [How does /proc/* work?](http://superuser.com/q/619955/53590) 感兴趣。 (2认同)