【发布时间】:2015-07-25 05:03:29
【问题描述】:
我试图了解链接器和加载器的操作,以及有关程序实际编译和执行方式的内存地址(物理或虚拟)。我遇到了两条信息,形成了我自己的理解版本。
第一条信息:
W.5.1 共享对象 在一个典型的系统中,许多程序将 正在运行。每个程序都依赖于许多功能,其中一些 这将是标准 C 库函数,如 printf()、malloc()、 strcpy() 等,有些是非标准或用户定义的函数。如果 每个程序都使用标准 C 库,这意味着每个程序 通常会存在此特定库的唯一副本 在其中。不幸的是,这会导致资源浪费,降低 效率和性能。 **由于C库是通用的,所以 最好让每个程序都引用公共的,一个实例 库,而不是让每个程序都包含该库的副本。 这是在链接过程中实现的,其中一些 对象在链接期间被链接,而一些在链接期间完成 运行时(延迟/动态链接)。 **
第二条信息:
C 库
主要文章:请参阅 C 库,创建 C 库 前面的一件事: 当您开始使用内核时,您没有 C 库 可用的。你必须自己提供一切,除了少数 编译器本身提供的片段。您还必须移植一个 现有的 C 库或自己编写一个。 C 库实现了 标准 C 函数(即,在 等)并以适合的二进制形式提供它们 用于与用户空间应用程序链接。除了标准 C 函数(在 ISO 标准中定义),C 库可能(和 通常确实)实现进一步的功能,这可能或可能 不是由某些标准定义的。标准 C 库什么也没说 例如,关于网络。对于类 Unix 系统,POSIX 标准定义了对 C 库的期望;其他系统 可能根本不同。需要注意的是,为了 实现其功能,C 库必须调用内核函数。 因此,对于您自己的操作系统,您当然可以使用现成的 C 库并 只需为您的操作系统重新编译它 - 但这需要您告诉 库如何调用你的内核函数,以及你的内核实际上 提供这些功能。更详细的示例可在 库调用,或者,您可以使用现有的 C 库或创建自己的 C 库。
我理解的方式:
当计算机启动时,它首先无法访问 C 库,而是必须使用机器代码。但是在引导代码的帮助下,它最终会开始加载操作系统。在此示例中,我将假设一台计算机加载 linux 操作系统。自然会加载一个linux内核。
当启动 linux 内核时,这也意味着标准 C 库(例如 printf 等基本函数)也被加载到低内存(分配给内核空间的 RAM 部分)。假设用户使用标准 C 库中的 printf() 编写了一个简单的代码。用户将编译此代码,在此过程中,链接器将为 printf() 进行“引用”,暗示 printf() 函数驻留在低内存中的位置。 执行此代码时,加载程序会将保存在 HDD 中的可执行文件加载到高内存(分配给用户空间的 RAM 部分)。当进程遇到 printf() 函数时,它会跳转到包含 printf() 函数开始的低内存地址。
我说的对吗?如果不是,我哪里错了?
【问题讨论】:
标签: linux linux-kernel linker loader