C中的动态链接库

amj*_*jad 2 c linker

我对C中的动态链接库有一些疑问。

Q1。 在此处输入图片说明

我的教科书使用图片说明DLL的工作方式,并且似乎复制了libvector.so和的一些重定位和符号表信息libc.so(箭头附在其侧面),但是每当汇编器遇到对最终位置未知的对象的引用时, ,它将生成一个重定位条目,告诉链接器将目标文件合并到可执行文件时如何修改引用。对于libc.so,一切都是已知的(具有所有定义),所以libc.so不应有任何重定位条目,不是吗?

Q2。我的教科书说:

“内存中共享库的.text部分的单个副本可以由不同的运行进程共享”,

假设我有一个使用的程序printf。是.textprintf一个程序结束时,驻留在RAM中的部分是永久保留还是从RAM中退出,而当第二个进程printf再次使用时,它会被加载到RAM中?如果是后者,那么由于我们有多个可以在后台运行的进程,将这.text部分printf移出并载入RAM的效率不是很高吗?

lan*_*u27 5

问题1: 您提供的图表对我来说似乎是正确的。据main2正被建造的; 搬迁和符号表信息libvector.so,并libc.so在使被复制,最终的可执行文件可以利用它们。从的角度来看main2,功能,常数等从libclibvector正在增加,所以我同意你的教科书的搬迁和符号表信息libvector.so以及libc.so被复制。

Q2: 您只呈现两个极端:“永远留在RAM中”或“在第一个程序完成时从RAM中退出”。几乎可以肯定,只要一些最近运行的进程使用了​​可共享部分,它们就将保留在RAM中。操作系统将使用的一种典型策略是LRU算法,以从RAM中驱逐“未使用”的东西,但是仅当它希望将更多的负载加载到RAM中时,才可以使用。因此,在使用很少的计算机上,几乎所有内容都可能在RAM中徘徊很长时间。但是在负担非常重的计算机上,操作系统将不断从RAM中丢弃需要很快恢复的内容。但是即使这样,某些事情还是被如此频繁地使用,它们不可能达到LRU阈值,因此您可能会在RAM中长时间存放某些事情,

第1季度的后续活动: 在评论中回答您的问题:正确:中没有main2.c定义的功能libc。正是因为这样,该连接器需要在搬迁和符号表信息复制printf()libc.so,这样当main2被执行时,libc.so也被载入。

更详细地:

printf()可能被称为main2.c,但printf()声明stdio.h定义在例如printf.c[1]和编译libc.so; main2.c可以编译因为编译器可以看到签名printf()(中stdio.h),而是建立main2(可执行文件),在已编译的代码libc.so需要被连接main2.o(中间目标文件)。 ld通过复制导致执行main2动态加载的引用来实现libc.so。[2]

[1]编译器在定义标准库函数方面会有所不同;gcc有一个printf.c定义的文件printf()(实际上是的传递vfprintf());其他编译器可能会采取不同的方式-但图书馆的整点是,你永远不要需要看看定义printf()库等功能; 您只需要来自适当文件的声明.h即可知道如何在您自己的文件中调用.c

[2]或者,如果您构建静态链接的可执行文件,则代码(不仅是符号表)将从库文件复制到正在构建的可执行文件中,并且即使在没有.so文件的计算机上也可以运行该可执行文件。动态链接或静态链接对于构建给定的可执行文件是否更好取决于几个因素。