我正在学习 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倍,只要运行 …
所以,我以为我对此有一个很好的理解,但只是进行了一个测试(以回应我不同意某人的对话)并发现我的理解有缺陷......
尽可能详细地说明当我在 shell 中执行文件时到底发生了什么?我的意思是,如果我输入:./somefile some arguments
进入我的 shell 并按回车键(并且somefile
存在于 cwd 中,并且我有读取+执行权限somefile
),那么引擎盖下会发生什么?
我以为答案是:
exec
,将路径传递给somefile
somefile
并查看文件的幻数,以确定它是否是处理器可以处理的格式somefile
被读取/映射到内存。创建堆栈并执行跳转到代码的入口点somefile
,并ARGV
初始化为参数数组 (a char**
, ["some","arguments"]
)exec()
如上所述生成一个新进程,但使用的可执行文件是shebang(例如/bin/bash
或/bin/perl
)引用的解释器并somefile
传递给STDIN
但是有人告诉我,如果文件是纯文本,那么 shell 会尝试执行命令(就像我输入了bash somefile
)。我不相信这一点,但我只是尝试了一下,结果是正确的。所以我显然对这里实际发生的事情有一些误解,并想了解机制。
当我在我的 shell 中执行一个文件时到底发生了什么?(尽可能多的细节是合理的......)
假设我帐户的默认 shell 是 zsh,但我打开了终端并启动了 bash 并执行了一个名为 的脚本prac002.sh
,哪个 shell 解释器将用于执行脚本,zsh 还是 bash?考虑以下示例:
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % sudo cat /etc/passwd | grep papagolf
[sudo] password for papagolf:
papagolf:x:1000:1001:Rex,,,:/home/papagolf:/usr/bin/zsh
# papagolf's default shell is zsh
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % bash
# I fired up bash. (See that '%' prompt in zsh changes to '$' prompt, indicating bash.)
papagolf@Sierra:~/My Files/My Programs/Learning/Shell$ ./prac002.sh
Enter username : Rex
Rex
# Which interpreter did it just use?
Run Code Online (Sandbox Code Playgroud)
**编辑:** 这是脚本的内容
papagolf@Sierra ~/My Files/My Programs/Learning/Shell …
Run Code Online (Sandbox Code Playgroud) 当我运行ls
. 我知道这些是可执行文件,并且我知道可以使用chmod
. 但它们是.csv
和.pdf
文件。我不明白如何“执行”逗号分隔的文本文件或 PDF。所以:
我按照迈克尔的回复 来查看我的 Ubuntu 可以识别执行哪些可执行格式
$ ls -l /proc/sys/fs/binfmt_misc/
total 0
-rw-r--r-- 1 root root 0 Apr 19 16:11 cli
-rw-r--r-- 1 root root 0 Apr 19 16:11 jar
-rw-r--r-- 1 root root 0 Apr 19 16:11 python2.7
-rw-r--r-- 1 root root 0 Apr 19 16:11 python3.5
--w------- 1 root root 0 Apr 19 16:11 register
-rw-r--r-- 1 root root 0 Apr 19 16:11 status
Run Code Online (Sandbox Code Playgroud)
我从来没有故意改变那里的任何东西,这些文件是默认创建的,或者是在我安装其他一些程序时创建的。
$ cat /proc/sys/fs/binfmt_misc/cli
enabled
interpreter /usr/lib/binfmt-support/run-detectors
flags:
offset 0
magic 4d5a
Run Code Online (Sandbox Code Playgroud)
这是一种什么样的可执行格式?我在 google 上搜索了“magic …
我不确定,动态链接器/usr/bin/ld
是由操作系统自动调用的,在加载 ELF 文件时,还是由嵌入在 ELF 文件中的代码调用?
当我r2
用来调试一个ELF文件时,它在第一条要执行的指令处停止,应该是动态链接器代码,但我不知道这段代码是不是ELF文件的一部分。
那里的情况有点奇怪。我为 ARM 平台(32 位)编译了 BusyBox 1.32.1 的静态可执行文件,奇怪的是它在两个平台上都没有问题。自己看:
root@smallbuntu /m/n/b/i/n/rootfs# readelf -h bin/busybox-initrd
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x1f419
Start of program headers: 52 (bytes into file)
Start of section headers: 1482800 (bytes into file)
Flags: 0x5000002, Version5 …
Run Code Online (Sandbox Code Playgroud)