C、c++:共享库:是加载到内存中的单个函数或完整库

C, C++: Shared libraries: Are single functions or complete libraries loaded into memory?

本文关键字:函数 单个 c++ 共享 加载 内存      更新时间:2023-10-16

使用静态编译,只有程序实际需要的库函数才链接到程序。共享库是怎样的呢?是否只有程序实际需要的函数被动态链接器加载到内存中,还是总是加载整个共享库?如果它是函数,我怎么能得到一个程序的实际大小,包括它在运行时加载的函数?

谢谢!奥利弗

使用静态编译,只有程序实际需要的库函数才链接到程序。

程序以符号方式引用共享库,也就是说,程序将通过名称识别与之链接的共享库。

动态连接器是否只将程序实际需要的函数加载到内存中,还是总是加载整个共享库?

程序将引用共享库中的特定入口点和数据对象。共享库将作为单个大对象映射到内存中,但是只有实际引用的页面才会被内核分页。加载库的总量将取决于引用的密度、链接到库的其他图像的引用以及库自身功能的位置。

如果它是函数,我怎么能得到一个程序的实际大小,包括它在运行时加载的函数

在Mac和其他基于unix的系统上最好的方法是使用ps(1)

静态链接时,只有(可能)被调用的函数被链接到可执行文件中——但在运行时,可执行文件中的数据将通过需求分页读取到内存中。

当进程创建时,地址被分配给该进程的可执行库和共享库中的所有代码,但此时文件中的代码/数据不一定被读入物理内存。当您尝试访问当前不在物理内存中的地址时,它将触发not-present异常。操作系统虚拟内存管理器将通过从文件中读取该页到物理内存来做出反应,而不是让访问继续进行。

加载是在逐页的基础上完成的,这通常意味着每次4或8千字节的块(例如,x86使用4K页,Alpha使用8k页)。x86也有能力创建更大(4兆字节)的页面,但这些页面并不(至少通常)用于普通代码——它们是用于映射大块内存,这些内存块保持永久映射(半),例如典型显卡上的内存"窗口",它也被映射,因此它可以被CPU直接访问。

大多数加载器都有一些优化,因此(例如)它们会在程序初始启动时尝试读取更大的内存块。这使得它的启动速度比中断和访问每一页代码时单独读取更快。这种优化的具体细节在不同的操作系统(通常甚至是相同操作系统的版本)之间是不同的。