c - C中的动态链接库
问题描述
我对 C 中的动态链接库有一些疑问。
我的教科书用一张图来说明DLL是如何工作的,貌似and的一些重定位和符号表信息libvector.so
被libc.so
复制了(箭头贴在他们旁边),但是每当汇编器遇到一个最终位置未知的对象的引用,它会生成一个重定位条目,告诉链接器在将目标文件合并到可执行文件时如何修改引用。对于 libc.so,一切都是已知的(它具有所有定义),所以不应该有任何 libc.so 的重定位条目,不是吗
Q2。我的教科书说:
“内存中共享库的 .text 部分的单个副本可以由不同的运行进程共享”,
假设我有一个使用printf
. 这.text
部分是printf
永远留在 RAM 中,还是在第一个程序完成时从 RAM 中逐出,并在第二个进程printf
再次使用时加载到 RAM 中?.text
如果是后者,由于我们有多个可以在后台运行的进程,因此该部分printf
被驱逐并多次加载到 RAM 中是不是非常低效?
解决方案
Q1: 您提供的图表对我来说似乎是正确的。它main2
正在建造中;libvector.so
和 的重定位和符号表信息libc.so
被复制进去,以便最终的可执行文件可以使用它们。从and的角度来看main2
,函数,常量等都是在添加的,所以我同意你的教科书,and 的重定位和符号表信息是被复制的。libc
libvector
libvector.so
libc.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.c
libc.so
main2.c
printf()
stdio.h
main2
libc.so
main2.o
ld
main2
libc.so
[1]编译器在标准库函数的定义方式上会有所不同;gcc
有一个printf.c
定义的文件printf()
(它实际上是传递给vfprintf()
);其他编译器可能会以不同的方式做这件事——但库的全部意义在于您不需要查看其他库函数的定义;printf()
您只需要相应文件中的声明.h
即可知道如何在您自己的文件中调用它。.c
[2]或者,如果您构建一个静态链接的可执行文件,代码(不仅仅是符号表)会从库文件复制到正在构建的可执行文件中,并且该可执行文件甚至可以在没有.so
文件存在的机器上运行. 动态链接还是静态链接更适合构建给定的可执行文件取决于几个因素。
推荐阅读
- c# - c#中的透视图
- flutter - Flutter Listview 滑动更改 TabBar 索引
- flutter - 颤振 pubspec.yaml 错误
- unit-testing - org.springframework.web.util.NestedServletException : 单元测试中的 MockMVC 请求处理失败
- javascript - React 如何管理生产中的状态
- python - 使用 Gekko 求解具有固定端点的最优控制
- python - pandas DataFrame中文本列的左对齐格式 - 不适用于空格
- python - 将 Matlab 代码转换为 Python 的有效方法
- python - 名称“app_config”未定义
- javascript - oracle apex 从 javascript 代码重定向到页面