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

标签 c linux executable elf

据我了解:

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

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

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

提前致谢。

最佳答案

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

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

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

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

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

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

关于c - 每个进程内存中的共享库是如何寻址的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65583507/

相关文章:

c++ - c - 如何在资源管理器中打开选定的文件

c - MPI Gatherv 不工作(消息被截断)

linux - 将用户添加到 sudoer 文件有什么作用?

c - Shell 重定向不会移动标准输出的文件位置

windows - 隐藏执行另一个 .EXE 文件的 .BAT 文件的命令窗口

c - 为在 void 函数中创建的动态数组赋值不会在 main() 中返回相同的值

c - 从数组构造二叉树的困难

linux - 使用提交后 Hook 时出现 SVN 提交合并错误

c++ - C++ 中的翻译单元与编译单元与目标文件与可执行文件与....

VB6将exe存储在exe中