共享对象加载到内存的程度

时间:2014-01-17 11:46:41

标签: gcc compiler-construction compilation shared-libraries compiler-optimization

如果有共享对象文件,则说libComponent.so由两个目标文件Component_1.o和Compononet_2.o组成。

还有一个链接到libComponent.so但只使用Compononent_1.o函数的应用程序。

当应用程序运行并使用共享对象文件或仅使用Component_1.o时,整个共享对象,即libComponent.so是否会被加载到内存中?

gcc编译器中是否有一个选项可以切换只从共享对象加载所需符号的行为?

1 个答案:

答案 0 :(得分:2)

嗯,这取决于'加载'的含义。

动态链接器将所有库映射到进程的虚拟内存空间,并将在可执行文件的导入表中填写与共享库中函数地址一起使用的每个库函数的条目。但填充导入表实际上并不从这些地址加载,因此它们不会被加载到物理内存中。

从那时起,当调用函数时,库代码将根据需要被分页到物理内存中,就像进程的虚拟地址空间中的任何其他可分页内存一样。如果一个函数永远不会被调用(直接来自应用程序或间接来自应用程序调用的另一个库函数),它将不会被分页。(好吧,分页是以页面大小粒度进行的,所以你可以在函数中引入一个函数如果它在它调用的函数旁边,则不会调用。有些编译器使用配置文件引导优化将通常一起调用的函数放在一起,以最大限度地减少使用的页面数。)

(旁白:如果您的库未编译为使用与位置无关的代码并且它的非默认基址加载,则链接器需要在加载时修复代码中的地址,这将导致整个要被分页的库。当每个页面首次加载时,这可以懒得完成,但我不确定哪个链接器会这样做。)