首页 > 解决方案 > C中的动态链接库

问题描述

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

Q1。 在此处输入图像描述

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

Q2。我的教科书说:

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

假设我有一个使用printf. 这.text部分是printf永远留在 RAM 中,还是在第一个程序完成时从 RAM 中逐出,并在第二个进程printf再次使用时加载到 RAM 中?.text如果是后者,由于我们有多个可以在后台运行的进程,因此该部分printf被驱逐并多次加载到 RAM 中是不是非常低效?

标签: clinker

解决方案


Q1: 您提供的图表对我来说似乎是正确的。它main2正在建造中;libvector.so和 的重定位和符号表信息libc.so被复制进去,以便最终的可执行文件可以使用它们。从and的角度来看main2,函数,常量等都是在添加的,所以我同意你的教科书,and 的重定位和符号表信息是被复制的。libclibvectorlibvector.solibc.so

Q2: 您只提出了两个极端:“永远留在 RAM 中”或“在第一个程序完成时从 RAM 中逐出”。几乎可以肯定,只要一些最近运行的进程使用了​​库的可共享部分,它们就会保留在 RAM 中。操作系统将使用的典型策略是 LRU 算法从 RAM 中逐出“未使用”的东西,但只有当它想要将更多的内容加载到 RAM 中时才会有空间。因此,在一台轻度使用的机器上,几乎所有东西都可能在 RAM 中停留很长时间;但是在一台负担过重的机器上,操作系统会不断地从 RAM 中丢弃它很快就会再次需要的东西。但即便如此,有些东西使用得如此频繁,它们不太可能达到 LRU 阈值,所以你可能会在 RAM 中长时间存放某些东西,

Q1 跟进: 在您的评论中回答您的问题:正确:没有任何内容main2.c可以定义libc. 正因为如此,链接器需要复制printf()from的重定位和符号表信息libc.so,以便在main2执行时libc.so也被加载。

更详细地说:

printf()可能从调用main2.c但在例如[1]printf()声明stdio.h定义并编译为; 可以编译,因为编译器可以看到(in ) 的签名,但是要构建(可执行文件),已经编译的代码需要(中间目标文件) 链接。 通过复制导致执行动态加载的引用来做到这一点。[2]printf.clibc.somain2.cprintf()stdio.hmain2libc.somain2.oldmain2libc.so

[1]编译器在标准库函数的定义方式上会有所不同;gcc有一个printf.c定义的文件printf()(它实际上是传递给vfprintf());其他编译器可能会以不同的方式做这件事——但库的全部意义在于您不需要查看其他库函数的定义printf()您只需要相应文件中的声明.h即可知道如何在您自己的文件中调用它。.c

[2]或者,如果您构建一个静态链接的可执行文件,代码(不仅仅是符号表)会从库文件复制到正在构建的可执行文件中,并且该可执行文件甚至可以在没有.so文件存在的机器上运行. 动态链接还是静态链接更适合构建给定的可执行文件取决于几个因素。


推荐阅读