我想从这里[1]理解dynamic库在Linux中的加载,并想澄清这个概念。 具体地说,当一个dynamic库被加载到Linux环境的一个进程中时,它被加载到地址空间中的任何一点。 现在,一个库有一个代码段和一个数据段。 代码段的地址没有被定义为预先链接,所以它是0x0000000,而对于数据段,一些编号被定义为一个地址。
但是这里有个诀窍,这个数据段的地址实际上并不是真正的地址。 实际上,无论在哪个位置加载代码段,都会将数据段的预定义地址添加到其中。
我在这里纠正?
还有一件来自引用的文章。 这个说法是什么意思?
但是,我们有一个约束,即共享库在每个进程中仍然必须有一个unqiue数据实例。 尽pipe可以在运行时将库数据放在任何地方,但是这需要留下重定位来修补代码,并通知它在哪里实际查找数据 – 破坏了代码的总是只读属性,从而破坏了可修改性。
[1] http://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html
实际上,无论在哪个位置加载代码段,都会将数据段的预定义地址添加到其中。
是。 数据段的“VirtAddr”将被添加到基地址。
这个说法是什么意思?
这意味着当库访问自己的静态数据时,我们不应该在库代码中使用重定位。 否则,链接器可能需要修补二进制代码,这会导致在进程之间取消库代码的某些部分(如果process1将库lib1加载到0x40000000,并且进程2将lib1加载到0x50000000,则其数据重定位将不同)。
所以,现实生活中使用不同的解决方案。 库代码和数据都被加载在一起,并且代码和数据之间的偏移对于所有情况是固定的。 您引用的文字后面有“解决方案”: http : //www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html
从上面的头文件可以看出,解决方法是读写数据段始终放在距库的代码段已知的偏移处。 这样,通过虚拟内存的魔力,每个进程都可以看到自己的数据部分,但可以共享未修改的代码。 所有需要访问数据的是一些简单的数学; 我想要的东西的地址=我的当前地址+已知的固定偏移量。