装载机到底是什么以及在哪里?
What and where exactly is the loader?
我了解 C 编译过程的每一点(如何链接目标文件以创建可执行文件)。但是关于加载程序本身(启动程序 运行)我有一些疑问。
加载程序是内核的一部分吗?
./firefox
或类似的命令究竟是如何加载的?我的意思是您通常会在终端中键入此类命令,该终端会加载我假定的可执行文件。那么loader是shell的一个组件吗?
我想我也对 terminal/shell 在所有这些中的位置以及它的作用感到困惑。
对应的系统调用为exec
。它是内核的一部分,负责清理进行调用的旧地址 space 并获取一个包含所有材料的新地址 运行 新代码。这是内核的一部分,因为地址 space 是一种保护进程免受其他进程影响的沙箱,并且由于它很关键,所以它负责内核。
shell 只负责解释您键入的内容并将其转换为适当的结构(列表或 C 字符串数组)以传递给某些 exec
调用(在拥有之后,大多数当时,使用 fork
).
生成了一个新进程
可执行文件的格式决定了它的加载方式。例如带有“#!”的可执行文件因为前两个字符由内核通过执行命名解释器并将文件作为第一个参数提供给它来加载。如果可执行文件被格式化为 PE、ELF 或 MachO 二进制文件,那么内核会使用内核内置的针对该格式的解释器来查找可执行代码和数据,然后选择下一步。
在动态链接 ELF 的情况下,下一步是执行动态加载程序(通常 ld.so)以查找库、加载它们并解析符号。这一切都发生在用户空间。内核或多或少不知道动态链接,因为这一切都发生在内核将控制权交给 ELF 文件中指定的解释器之后的用户空间中。
我了解 C 编译过程的每一点(如何链接目标文件以创建可执行文件)。但是关于加载程序本身(启动程序 运行)我有一些疑问。
加载程序是内核的一部分吗?
./firefox
或类似的命令究竟是如何加载的?我的意思是您通常会在终端中键入此类命令,该终端会加载我假定的可执行文件。那么loader是shell的一个组件吗?
我想我也对 terminal/shell 在所有这些中的位置以及它的作用感到困惑。
对应的系统调用为exec
。它是内核的一部分,负责清理进行调用的旧地址 space 并获取一个包含所有材料的新地址 运行 新代码。这是内核的一部分,因为地址 space 是一种保护进程免受其他进程影响的沙箱,并且由于它很关键,所以它负责内核。
shell 只负责解释您键入的内容并将其转换为适当的结构(列表或 C 字符串数组)以传递给某些 exec
调用(在拥有之后,大多数当时,使用 fork
).
可执行文件的格式决定了它的加载方式。例如带有“#!”的可执行文件因为前两个字符由内核通过执行命名解释器并将文件作为第一个参数提供给它来加载。如果可执行文件被格式化为 PE、ELF 或 MachO 二进制文件,那么内核会使用内核内置的针对该格式的解释器来查找可执行代码和数据,然后选择下一步。
在动态链接 ELF 的情况下,下一步是执行动态加载程序(通常 ld.so)以查找库、加载它们并解析符号。这一切都发生在用户空间。内核或多或少不知道动态链接,因为这一切都发生在内核将控制权交给 ELF 文件中指定的解释器之后的用户空间中。