Mono有多神奇?
我正在學習 C#,所以我做了一個小 C# 程序,上面寫著
Hello, World!
,然後編譯它mono-csc
並執行它mono
:$ mono-csc Hello.cs $ mono Hello.exe Hello, World!
我注意到當我點擊
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..............
MZ
表示它是 Microsoft Windows 靜態連結的執行檔。把它放到一個 Windows 盒子上,它會(應該)執行。我已經
wine
安裝了,但是wine
,作為 Windows 應用程序的兼容層,執行和直接執行它所需的時間大約是 5 倍Hello.exe
,mono
所以它不是wine
執行它。我假設
mono
安裝了一些核心模組mono
來攔截exec
系統呼叫/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"); } }
這就是binfmt_misc的作用:它允許告訴核心如何執行它不知道的二進製文件。看內容
/proc/sys/fs/binfmt_misc
;在您在那裡看到的文件中,應該解釋如何執行 Mono 二進製文件:enabled interpreter /usr/lib/binfmt-support/run-detectors flags: offset 0 magic 4d5a
(在 Debian 系統上)。這告訴核心應將
MZ
( )開頭的二進製文件提供給. 後者確定是使用 Mono 還是 Wine 來執行二進製文件。4d5a``run-detectors
二進制類型可以隨時添加、刪除、啟用和禁用;有關詳細資訊,請參閱上面的文件(語義令人驚訝,這裡使用的虛擬文件系統的行為並不完全像標准文件系統)。
/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
暫時禁用…