据我了解:
当您将代码编译成二进制文件时,无需转换该二进制文件中的地址。由于每个进程都有自己的内存空间,二进制文件中使用的地址可以在运行时使用。
但是如果你有一个共享库,它是如何映射到进程内存空间的呢?如果库代码使用虚拟内存地址,则必须为库映射到不同虚拟内存地址的每个进程更改它们。
我在这方面不是很有经验(正如您可能猜到的那样),如果有任何非常错误的地方,我们深表歉意。
提前致谢。
最佳答案
在 Linux 中,当在您的代码中有效调用库时,默认情况下会解析对共享库的引用。这称为惰性出价。因此,处理器不能执行所有二进制文件。它们中的大多数实际上是被解释的(参见 /lib64/ld-linux-*.so
)。
为了执行此操作,ELF 二进制文件包含两个特定的表:
- 程序链接表 (PLT)
- 全局偏移表 (GOT)
您正在执行的代码引用了执行重定向的 PLT。在第一次调用时,GOT 将包含一个回调地址,如果执行该地址,它将跳转到加载程序,加载程序将地址解析为动态库。该库映射到您程序的虚拟内存中,即使它只在您的物理内存中出现一次。
您正在使用虚拟内存,因此您的进程看到的地址可能会有所不同,因此每个进程使用一个 GOT。至于使用两个表:主要是出于安全原因,因此您永远不会从可写页面执行指令。
如果您愿意,可以通过设置 LD_BIND_NOW
环境变量来禁用惰性出价。
关于c - 每个进程内存中的共享库是如何寻址的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65583507/