动态加载的函数库Dynamically loaded (DL) libraries是一类函数库,它可以在程序运行过程中的任何时间加载。它们特别适合在函数中加载一些模块和plugin扩展模块的场合,因为它可以在当程序需要某个plugin模块时才动态的加载。例如,Pluggable Authentication Modules(PAM)系统就是用动态加载函数库来使得管理员可以配置和重新配置身份验证信息。

Linux系统下,DL函数库与其他函数库在格式上没有特殊的区别,我们前面提到过,它们创建的时候是标准的object格式。主要的区别就是这些函数库不是在程序链接的时候或者启动的时候加载,而是通过一个API来打开一个函数库,寻找符号表,处理错误和关闭函数库。通常C语言环境下,需要包含这个头文件。 
        Linux中使用的函数和Solaris中一样,都是dlpoen() API。当然不是所有的平台都使用同样的接口,例如HP-UX使用shl_load()机制,而Windows平台用另外的其他的调用接口。如果你的目的是使得你的代码有很强的移植性,你应该使用一些wrapping函数库,这样的wrapping函数库隐藏不同的平台的接口区别。一种方法是使用glibc函数库中的对动态加载模块的支持,它使用一些潜在的动态加载函数库界面使得它们可以夸平台使用。具体可以参考http://developer.gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html. 另外一个方法是使用libltdl,是GNU libtool的一部分,可以进一步参考CORBA相关资料。

1.1. dlopen()
dlopen函数打开一个函数库然后为后面的使用做准备。C语言原形是:

void * dlopen(const char *filename, int flag);

如果文件名filename是以“/”开头,也就是使用绝对路径,那么dlopne就直接使用它,而不去查找某些环境变量或者系统设置的函数库所在的目录了。否则dlopen()就会按照下面的次序查找函数库文件:
       1. 环境变量LD_LIBRARY指明的路径。

2. /etc/ld.so.cache中的函数库列表。

3. /lib目录,然后/usr/lib。不过一些很老的a.out的loader则是采用相反的次序,也就是先查 /usr/lib,然后是/lib。
    dlopen()函数中,参数flag的值必须是RTLD_LAZY或者RTLD_NOW,RTLD_LAZY的意思是resolve undefined symbols as code from the dynamic library is executed,而RTLD_NOW的含义是resolve all undefined symbols before dlopen() returns and fail if this cannot be done'。
    如果有好几个函数库,它们之间有一些依赖关系的话,例如X依赖Y,那么你就要先加载那些被依赖的函数。例如先加载Y,然后加载X。

dlopen()函数的返回值是一个句柄,然后后面的函数就通过使用这个句柄来做进一步的操作。如果打开失败dlopen()就返回一个NULL。如果一个函数库被多次打开,它会返回同样的句柄。 
    如果一个函数库里面有一个输出的函数名字为_init,那么_init就会在dlopen()这个函数返回前被执行。我们可以利用这个函数在我的函数库里面做一些初始化的工作。我们后面会继续讨论这个问题的。  
1.2. dlerror()

通过调用dlerror()函数,我们可以获得最后一次调用dlopen(),dlsym(),或者dlclose()的错误信息。 
1.3. dlsym()

如果你加载了一个DL函数库而不去使用当然是不可能的了,使用一个DL函数库的最主要的一个函数就是dlsym(),这个函数在一个已经打开的函数库里面查找给定的符号。这个函数如下定义:

void * dlsym(void *handle, char *symbol);

函数中的参数handle就是由dlopen打开后返回的句柄,symbol是一个以NIL结尾的字符串。如果dlsym()函数没有找到需要查找的symbol,则返回NULL。如果你知道某个symbol的值不可能是NULL或者0,那么就很好,你就可以根据这个返回结果判断查找的symbol是否存在了;不过,如果某个symbol的值就是NULL,那么这个判断就有问题了。标准的判断方法是先调用dlerror(),清除以前可能存在的错误,然后调用dlsym()来访问一个symbol,然后再调用dlerror()来判断是否出现了错误。一个典型的过程如下:

[cpp] view plaincopy
  1. dlerror();      /*clear error code */
  2. s = (actual_type)dlsym(handle, symbol_being_searched_for);
  3. if((error = dlerror()) != NULL){
  4. /* handle error, the symbol wasn't found */
  5. } else {
  6. /* symbol found, its value is in s */
  7. }

1.4. dlclose()

dlopen()函数的反过程就是dlclose()函数,dlclose()函数用力关闭一个DL函数库。Dl函数库维持一个资源利用的计数器,当调用dlclose的时候,就把这个计数器的计数减一,如果计数器为0,则真正的释放掉。真正释放的时候,如果函数库里面有_fini()这个函数,则自动调用_fini()这个函数,做一些必要的处理。Dlclose()返回0表示成功,其他非0值表示错误。

1.5. DL Library Example

下面是一个例子。例子中调入math函数库,然后打印2.0的余弦函数值。例子中每次都检查是否出错。应该是个不错的范例:

[cpp] view plaincopy
  1. int main(int argc, char *argv){
  2. void *handle;
  3. char *error;
  4. double (*cosine )(double);
  5. handle = dlopen("/lib/libm.so.6", RTLD_LAZY);
  6. if(!handle){
  7. fputs(dlerror(), stderr);
  8. exit(1);
  9. }
  10. cosine = dlsym(handle, "cos");
  11. if((error = dlerror()) != NULL){
  12. fputs(error, stderr);
  13. exit(1);
  14. }
  15. printf("%f", (*cosine)(2, 0));
  16. dlclose(handle);
  17. return 0;
  18. }

如果这个程序名字叫foo.c,那么用下面的命令来编译:

gcc -o foo foo.c –ldl

动态加载的函数库Dynamically Loaded (DL) Libraries相关推荐

  1. ANDROID动态加载 使用SO库时要注意的一些问题

    转载自:http://blog.csdn.net/qq_23331691/article/details/51699888 基本信息 作者:kaedea 项目:android-dynamical-lo ...

  2. thinkphp3.2加载第三方函数库

    为什么80%的码农都做不了架构师?>>>    封装好一个函数库(文件命名为myfunction.php)//这是函数库的其中一个方法 /*** 定义一个跳转的方法*@param s ...

  3. 从DLL中动态加载一个函数:LoadLibrary和GetProcAddress的使用

    背景描述: 在项目CDP_cmd中需要调用项目CDP_dgnCalc中的类CAnalRstHelper_JTGTJ212011的函数: BOOL GetElemValuePositiveOrNegat ...

  4. Linux下的静态库、动态库和动态加载库

    from: http://www.techug.com/linux-static-lib-dynamic-lib 库的存在极大的提高了C/C++程序的复用性,但是库对于初学者来说有些难以驾驭,本文从L ...

  5. 动态加载so库的实现方法与问题处理

    前一阵项目上要求实现App的so库动态加载功能,因为这块本来就有成熟的方案,所以一般的实现没什么难度.可是到项目测试中,才发现有不少意料之外的情况,需要一一针对处理,故此记录一下具体的解决办法,以供后 ...

  6. android 动态加载sdk,LiteAVSDK集成,因此可以动态加载库

    在Android开发中,Android Studio用于集成第三方SDK(例如,腾讯视频云移动直播,播放器,短视频以及实时音频和视频). 通常有两种集成方法: aar集成和jar + so集成. An ...

  7. pyqt5 和 pySinde2 动态加载 QT Designer

    加粗样式@TOC from PyQt5 import uic # 导入 动态加载 ui文件 库 from PyQt5.QtWidgets import QApplication, QMainWindo ...

  8. CUDA CUBIN/PTX文件动态加载

    程序演示了如何动态加载CUBIN/PTX文件并执行其中的函数,包含cubin.cu.main.cu两个文件.其中cubin.cu包含需要被动态加载的函数kernel_run. cubin.cu #in ...

  9. 【Android 逆向】加壳技术简介 ( 动态加载 | 第一代加壳技术 - DEX 整体加固 | 第二代加壳技术 - 函数抽取 | 第三代加壳技术 - VMP / Dex2C | 动态库加壳技术 )

    文章目录 一.动态加载 二.第一代加壳技术 ( DEX 整体加固 ) 三.第二代加壳技术 ( 函数抽取 ) 四.第三代加壳技术 ( Java 函数 -> Native 函数 ) 五.so 动态库 ...

最新文章

  1. 一个程序猿和非程序猿都会关注的重大事件
  2. 常用 Git 命令清单(阮一峰)
  3. html中下拉日历控件,HTML5之日历控件
  4. 淘宝现在什么类目比较好做?
  5. 从概念入手,了解AWS在Iaas、Paas,Saas层的服务
  6. PWM呼吸灯(小白版)
  7. TIM2_CH1_ETR可以当做TIM2_CH1来用
  8. 直播回顾|关联网络如何反团伙欺诈——标准答案版
  9. 2021年中国家具制造业经营现状分析:营业收入达8004.6亿元,利润总额达433.7亿元[图]
  10. 原码,反码,补码,全面解析
  11. Yamaha DGX660 电钢琴aux-in只响一边的处理记录
  12. C. Keshi Is Throwing a Party(二分答案),最/佳牛围栏,average。
  13. STM32F407ZET6的RTC闹钟二次设置笔记
  14. 提高期英语学习——第二次罗塞塔
  15. HDU-2094(产生冠军)
  16. bootstrap 表单验证
  17. ArcGIS Server发布地理处理(GP)服务并调用
  18. ABP VNext系列(一)-第一个ABP VNext
  19. 五年级计算机学情分析,小学五年级信息技术教案教学计划
  20. 使用webpack打包vue项目

热门文章

  1. 七夕祭(贪心、难点)
  2. 干货丨 艾建松:深瞳云涂大数据支撑户外媒体投放策略及效果监测
  3. WRONGTYPE Operation against a key holding the wrong kind of value 解决处理
  4. **超防 ja3+加速乐(三种加密(md5,sha1,sha256)) 实战(python爬虫js逆向)
  5. Egret List
  6. JavaSE——第23章 反射reflection
  7. C语言计算某年某月有多少天
  8. Oracle 实例管理
  9. 2019.1.2 数字转换为16进制
  10. 成功激活了Win10正式专业版系统。