如果我构建一个共享库(共享对象),我可以通过以下两种方式使用它:
第一种方法是使用共享库,就像我使用静态库一样。
#include "myLib.h"
//...
//afterwards I can use functions defined in mylib.h
myFunction();
使用共享库的第二种方法是调用动态加载器API函数:dlopen
,dlsym
和dlclose
来自dlfcn.h
。例如,当我想实现插件模式时,我会以这种方式使用共享库。清单看起来像这样:
#include <dlfcn.h>
void *myLib; /* Handle to shared lib file */
void (*myFunction)(); /* Pointer to loaded function */
//...
//load shared object
myLib = dlopen("/home/dlTest/myLib.so",RTLD_LAZY);
dlerror();
//get handle to function
myFunction = dlsym( myLib, "myFunction");
dlerror();
//execute function
(*myFunction)();
//close lib
dlclose(myLib);
dlerror();
现在我的第一个问题是:在加载时间方面,共享对象的这两种用法有什么区别?通过第一种方式使用共享库,我们在加载时将链接/加载到主应用程序,在第二种方式我们在运行时做同样的事情?
第二个问题。这两种用法的名称是什么? 第一个是静态链接共享库,第二个是动态链接/加载共享库?
第三个问题如果我构建了一个没有-fPIC
标志(独立代码)的共享库,我能否以第二种方式使用它?
干杯
答案 0 :(得分:5)
这两种使用模式通常称为隐式和显式。正确地说明了加载的不同之处在于,当执行dlopen时加载了显式链接的动态库,并且在应用程序加载到内存时加载了隐式链接库。每个dlopen可能需要几毫秒才能完成,除非已经加载了库,在这种情况下它非常快,所以如果你有非常严格的延迟要求或需要经常加载/卸载那么你可能决定隐式或显式加载库在程序启动时,不要卸载它,直到它不再使用。
答案 1 :(得分:5)
主要区别在于错误处理。隐式更容易,但如果出现问题(库缺失或函数不在库中),程序将无法运行。使用显式加载,您可以检查dlopen / dlsym调用是否存在错误,如果出现问题,可以使用其他替代方法。
要回答第三个问题,它实际上取决于体系结构,但在大多数ABI上,您仍然可以加载不使用-PIC编译的共享对象,但加载速度可能较慢并需要更多内存。