【问题标题】:Understanding Dynamic Library loading in Linux了解 Linux 中的动态库加载
【发布时间】:2014-03-20 17:09:55
【问题描述】:

我试图从这里 [1] 了解 Linux 中的动态库加载,并想澄清这个概念。具体来说,当动态库在 Linux 环境中的进程中加载​​时,它会在地址空间中的任何点加载。现在,一个库有一个代码段和一个数据段。代码段的地址在链接前没有定义,所以它是0x0000000,而对于数据段,一些数字被定义为地址。

但这里有个窍门,这个数据段的地址实际上并不是真正的地址。实际上,在加载代码段的任何位置,都会将数据段的预定义地址添加到其中。

我说的对吗?

参考文章中的另一件事。这个声明是什么意思?

但是,我们有一个约束,即共享库在每个进程中仍然必须有一个 unqiue 数据实例。虽然可以在运行时将库数据放在我们想要的任何位置,但这需要留下重定位来修补代码并通知它在哪里实际找到数据——破坏代码的始终只读属性,从而破坏可共享性。

[1]http://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html

【问题讨论】:

  • 问题是什么?

标签: c++ c linux shared-libraries


【解决方案1】:

实际上,在代码段加载的任何位置,都会添加数据段的预定义地址。

是的。数据段的“VirtAddr”将被添加到基地址。

这句话是什么意思?

这意味着当库访问自己的静态数据时,我们不应该在库代码中使用重定位。否则链接器可能需要修补二进制代码,这会导致进程之间不共享库代码的某些部分(如果 process1 在 0x40000000 加载库 lib1,而 process2 在 0x50000000 加载 lib1,它们的数据重定位将不同)。

因此,在现实生活中使用了不同的解决方案。库代码和数据一起加载,代码和数据之间的偏移量在所有情况下都是固定的。您引用的文字后面有“解决方案”:http://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html

从上面的标题中可以看出,解决方案是读写数据部分始终放置在库代码部分的已知偏移量处。这样,通过虚拟内存的魔力,每个进程都可以看到自己的数据部分,但可以共享未修改的代码。访问数据所需要的只是一些简单的数学运算;我想要的东西的地址 = 我当前的地址 + 已知的固定偏移量。

【讨论】:

  • 通过 GOT/PLT 访问具有外部链接的数据,而不是通过偏移量。类似于外部函数。
猜你喜欢
  • 1970-01-01
  • 2014-06-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2020-02-27
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多