每个进程内存中的共享库是如何寻址的?

How are shared libraries addressed in each processes memory?

据我了解:

将代码编译成二进制文件时,无需转换二进制文件中的地址。由于每个进程都有自己的内存space,二进制文件中使用的地址可以在运行时使用。

但是,如果您有共享库,如何将它映射到进程内存中 space?如果库代码使用虚拟内存地址,则必须为库映射到不同虚拟内存地址的每个进程更改它们。

我在这方面不是很有经验(你可能猜到了),如果有任何非常错误的地方,我们深表歉意。

提前致谢。

在 Linux 中,当在您的代码中有效调用共享库时,默认情况下会解析对共享库的引用。这称为惰性出价。因此处理器不会执行所有二进制文件table。其中大部分实际上是经过解释的(参见 /lib64/ld-linux-*.so)。

为了执行此操作,ELF 二进制文件包含两个特定的 tables :

  • 程序链接 table (PLT)
  • 全局偏移量table (GOT)

您正在执行的代码引用了执行重定向的 PLT。在第一次调用时,GOT 将包含一个回调地址,如果执行该地址,它将跳转到加载程序,加载程序将地址解析为动态库。该库映射到您程序的虚拟内存中,即使它只在您的物理内存中出现一次。

您正在使用虚拟内存,因此您的进程看到的地址可能会有所不同,因此每个进程使用一个 GOT。至于两个 table 的使用:主要是出于安全原因,因此您永远不会从 writable 页面执行指令。

如果您愿意,可以通过设置 LD_BIND_NOW 环境变量来禁用延迟出价。