为什么动态库源代码应该使用与位置无关的代码进行编译



我对位置无关代码及其在动态库中的使用感到非常困惑。

我发现了一个关于GCC的-fPIC选项的好例子:GCC-fPIC选项我弄清楚它是如何工作的。

然而,我很难理解为什么动态库需要独立于特定地址的代码。当加载动态库时,为什么我们不能只保存它的绝对地址(例如库中函数的地址(并使用它们?为什么在这种情况下必须使用相对地址?

一个简单的程序CCD_;gcc-main.c";是否总是取决于位置?

-fPIC决不是共享库问题的唯一解决方案。在ELF之前,Linux使用a.out可执行文件格式。在a.out中,所有共享库都使用全局地址空间中的唯一地址,因此所有进程总是将它们加载到相同的固定地址。事实证明,这极难管理:所有发行版包都必须在彼此之间就为哪个库保留哪个地址范围达成一致,并随着库的发展不断修改这一协议。

-fPIC让我们摆脱了困境。

根据您的建议,全局动态保留所有进程的地址范围,一旦某个进程将库映射到某个内存区域,即使其他进程从未实际加载库,也无法重用该区域。对于具有4G地址空间的32位系统(或者甚至2G是更高的2G为内核保留(,这可能会快速耗尽VM。另一个问题来自于这样一个事实,即主可执行文件的大小在不同的进程中是不同的,所以并没有全局启动地址可以安全地加载库。

最新更新