关于Unix上共享库的困境

时间:2010-12-10 17:05:30

标签: c++ linux unix shared-libraries

如果我构建一个共享库(共享对象),我可以通过以下两种方式使用它:
第一种方法是使用共享库,就像我使用静态库一样。

           #include "myLib.h"
           //...
           //afterwards I can use functions defined in mylib.h
           myFunction();

使用共享库的第二种方法是调用动态加载器API函数:dlopendlsymdlclose来自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标志(独立代码)的共享库,我能否以第二种方式使用它?

干杯

2 个答案:

答案 0 :(得分:5)

这两种使用模式通常称为隐式和显式。正确地说明了加载的不同之处在于,当执行dlopen时加载了显式链接的动态库,并且在应用程序加载到内存时加载了隐式链接库。每个dlopen可能需要几毫秒才能完成,除非已经加载了库,在这种情况下它非常快,所以如果你有非常严格的延迟要求或需要经常加载/卸载那么你可能决定隐式或显式加载库在程序启动时,不要卸载它,直到它不再使用。

答案 1 :(得分:5)

主要区别在于错误处理。隐式更容易,但如果出现问题(库缺失或函数不在库中),程序将无法运行。使用显式加载,您可以检查dlopen / dlsym调用是否存在错误,如果出现问题,可以使用其他替代方法。

要回答第三个问题,它实际上取决于体系结构,但在大多数ABI上,您仍然可以加载不使用-PIC编译的共享对象,但加载速度可能较慢并需要更多内存。