C,C ++:共享库:单个函数还是完整的库加载到内存中?

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

谢谢 ! 奥利弗

通过静态编译,只有程序实际需要的库函数才能链接到程序。 这是如何与共享库?

共享库是由程序象征性地引用的,也就是说,程序将通过名称来识别它所链接的共享库。

只有程序实际需要的函数被动态链接器加载到内存中,还是总是加载共享库?

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

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

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

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

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

加载是逐页完成的,通常意味着一次4或8千字节的块(例如,x86使用4K页面,Alpha使用8k)。 x86也有能力创建更大的(4兆字节)页面,但是那些不是(至少通常)用于普通代码 – 它们用于映射永久映射(半)的大块内存,例如作为一个典型的显卡上的内存“窗口”,这也是映射,所以它可以直接由CPU访问。

大多数装载机都有一些优化,所以(例如)当程序最初启动时,它们会尝试读取更大的内存块。 这使得它可以比在访问每个代码页时发生中断和单独读取更快地启动。 这种优化的确切细节因操作系统而异(通常甚至是同一操作系统的版本)。