只完成了最少量的工作 在编译时由链接器;它只是 记录库的例程 程序需求和索引名称或 中的例程数量 图书馆。 (source)
所以这意味着ld.so
不会检查其数据库中的所有库,只检查应用程序程序本身记录的那些库,也就是说,只检查gcc -lxxx
指定的库。
这与我之前的知识相矛盾,即ld.so
将逐个检查其数据库中的所有库,直到找到它为止。
具体情况如何?
答案 0 :(得分:4)
我会回答这个问题......
在链接时,链接器(不是ld.so)将确保链接在一起的.o文件的所有符号都被程序链接到的库满足。如果这些库中的任何库是动态库,它还将检查它们所依赖的库(不需要将它们包含在-l
列表中),以确保满足这些库中的所有符号。它会递归地执行此操作。
只有可执行文件在链接时直接依赖于via提供的-l
参数的库才会记录在可执行文件中。如果库本身声明了依赖项,那么这些依赖项将不会记录在可执行文件中,除非这些库在链接时也使用-l
标志指定。
运行链接器时会发生链接。对于gcc,这通常看起来像gcc a.o b.o c.o -lm -o myprogram
。这通常发生在编译过程结束时。在封面下,它通常运行一个名为ld
的程序。但是ld
与ld.so
(运行时加载器)完全不同。尽管它们是不同的实体,但它们的名称相似,因为它们在不同的时间执行类似的工作。
加载是运行程序时发生的步骤。对于动态库,如果使用静态库,则加载器会执行链接器将执行的大量任务。
当程序运行时,ld.so(运行时加载程序)实际上将可执行文件上的符号挂钩到共享库中的定义。如果该共享库依赖于其他共享库(记录在库中的事实),它也将加载这些库并将其连接到它们。如果在完成所有这些操作后仍然存在未解析的符号,则加载程序将中止该程序。
因此,可执行文件说明了它直接依赖的动态库。每个库都说明了它们直接依赖的动态库,依此类推。加载器(ld.so)使用它来决定查找符号的库。它不会搜索“数据库”中的随机其他库来查找适当的符号。它们必须位于依赖链中的库中。