我今天无意中发现了这件事情,刚写了个 C 语言的 hello world,用 mingw 交叉编译了一下。
代码如下:
/*
* 一个 C 语言的 hello world 程序:a.c
* 我用 mingw 编译了 a.c 并获得了下面的 a.exe:
* x86_64-w64-mingw32-gcc a.c
*/
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("-- it starts --\n");
sleep(10);
printf("-- it ends --\n");
return 0;
}
然后,调试的时候,我本来是想执行:
wine ./a.exe
然后失手打成了:
./a.exe
这个。。。居然成功运行了。。。
然后,我用 hexdump 检查了一下这个 a.exe,确认了这个确实不是 ELF 格式的,而是 Windows 的 PE 格式的 binary:
# hexdump -C a.exe | less 得到的文件头部内容:
00000000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 |MZ..............|
00000010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 |................|
00000040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 |........!..L.!Th|
00000050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f |is program canno|
00000060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 |t be run in DOS |
00000070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 |mode....$.......|
00000080 50 45 00 00 64 86 11 00 f5 4e 8c 5d 00 7a 05 00 |PE..d....N.].z..|
00000090 0a 06 00 00 f0 00 27 00 0b 02 02 20 00 1e 00 00 |......'.... ....|
000000a0 00 3c 00 00 00 0a 00 00 f0 14 00 00 00 10 00 00 |.<..............|
000000b0 00 00 40 00 00 00 00 00 00 10 00 00 00 02 00 00 |..@.............|
000000c0 04 00 00 00 00 00 00 00 05 00 02 00 00 00 00 00 |................|
000000d0 00 20 06 00 00 06 00 00 f7 bf 06 00 03 00 00 00 |. ..............|
000000e0 00 00 20 00 00 00 00 00 00 10 00 00 00 00 00 00 |.. .............|
000000f0 00 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00 |................|
00000100 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
00000110 00 80 00 00 6c 07 00 00 00 00 00 00 00 00 00 00 |....l...........|
00000120 00 50 00 00 7c 02 00 00 00 00 00 00 00 00 00 00 |.P..|...........|
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
后来,我在 sleep(10) 的过程中按下了 ctrl + C,然后这个东西 print 了一行看起来是由 wine 输出的日志:
$ ./a.exe
-- it starts --
^C002f:fixme:console:CONSOLE_DefaultHandler Terminating process 2d on event 0
然后,我就想:会不会是 zsh 发现这个是个 Windows 的 binary,所以就自动帮我调用了 wine。
于是,我换成 bash 和 sh 各试了一遍,结果一样,还是可以直接执行 ./a.exe,并且仍然可以在 sleep(10) 的过程中用 ctrl + C 中断并使其输出这条 wine 的日志。
那么,看起来并不是 shell 的关系(这里我假设了功能上比较原始的 sh 不会在这种事情上动手脚,我并不是很确定)。
那么,这是怎么回事呢?为什么我的系统会自动调用 wine 来执行 Windows PE 格式的文件呢?
如果说,shell 没有在这件事情上动手脚的话,那么,是谁调出来了 wine 呢?而且内核和 ld 不是应该只认 ELF 格式的 binary 吗
最近编辑记录 Mr.I (2019-09-26 14:53:34)
离线
是 wine 註冊了內核的 binfmt_misc 作爲 PE 文件的解釋器。
$ cat /proc/sys/fs/binfmt_misc/DOSWin
enabled
interpreter /usr/bin/wine
flags:
offset 0
magic 4d5a
wine 包提供了 /usr/lib/binfmt.d/wine.conf 這個文件, systemd 在啓動的時候 systemd-binfmt.service 服務會讀取其中的文件註冊 binfmt_misc。
computerは神様だと信じていて
だからVIMの上でずっと指が舞って
自ら恋愛相手を作り出して
离线
是 wine 註冊了內核的 binfmt_misc 作爲 PE 文件的解釋器。
$ cat /proc/sys/fs/binfmt_misc/DOSWin enabled interpreter /usr/bin/wine flags: offset 0 magic 4d5a
wine 包提供了 /usr/lib/binfmt.d/wine.conf 這個文件, systemd 在啓動的時候 systemd-binfmt.service 服務會讀取其中的文件註冊 binfmt_misc。
好棒的回答,非常感谢!
我感觉我打开了新世界的大门了
离线
已经是本论坛少有的正常画风的问答帖了。
反社会,精神极其不稳定,随时可能炸碎身边所有人
离线