现在的位置: 首页 > 综合 > 正文

Linux中动态链接库总结

2018年03月21日 ⁄ 综合 ⁄ 共 4596字 ⁄ 字号 评论关闭

#参考:
#    http://www.abc188.com/info/html/wangzhanyunying/jianzhanjingyan/20080417/70810.html
#    http://os.51cto.com/art/201001/176625.htm
#    http://os.51cto.com/art/201001/176618.htm

[概述]本文是我在学习linux下动态链接库的总结,主要内容为:为什么要使用动态链接库、动态链接库的制作、使用。

0 为什么要使用动态链接库


    linux下的库文件有:静态库和动态库两种。静态库文件的制作和使用在前文中已简要总结。LINUX系统中动态链接库,类似于 WINDOWS中以.dll为后缀的文件(dll即Dynamic Link Library)。
    静态库与动态库的区别。如果程序是在编译时加载库文件的,就是使用了静态库。如果是在运行时加载目标代码,就成为动态库。换句话说,如果是使用静态库,则静态库代码在编译时就拷贝到了程序的代码段,程序的体积会膨胀。如果使用动态库,则程序中只保留库文件的名字和函数名,在运行时去查找库文件和函数体,程序的体积基本变化不大。
    静态库的原则是“以空间换时间”,增加程序体积,减少运行时间;
    动态库则是“以时间换空间”,增加了运行时间,但减少了程序本身的体积。
   
1 动态链接库的制作


    在LINUX系统下,创建动态链接库是件非常简单的事情。只要在编译函数库源程序时加上-shared选项即可,这样所生成的执行程序即为动态链接库。从某种意义上来说,动态链接库也是一种执行程序。按一般规则,动态库的命名应为lib*.so.*。其中第一个*为动态库的名字,第二个*为版本号,比如libc.so.6。编译生成动态库的命令: gcc -o libmy.so -fpic -shared getdate.c gettime.c
    下面制作动态库的例子中有3个文件: adatetime.h, getdate.c, gettime.c。adatetime.h为动态链接库的头文件; getdate.c和gettime.c分别实现getDate()和getTime()函数。
1.1 编写动态库头文件adatetime.h,代码如下:

1.2 编写getdate.c和gettime.c,代码如下:

1.3 编译生成动态库
(1) 编写维护文件makefile-lib,内容如下

注意: 每行维护代码必须以TAB(跳格键)开始,不是的话make时将出错。
编写维护文件的目的,在于方便程序员维护程序,尤其是维护比较大的工程项目。
(2) 运行命令make -f makefile-lib, 则生成名为libmy.so的动态库文件。

1.4 共享动态库文件
    /etc/ld.so.conf文档中,存放着可被LINUX共享的动态链接库所在目录的名字(系统目录/lib,/usr/lib除外)。我们可以把自己制作的动态库放到/lib或/usr/lib;也可以新建用户自己的库文件夹:/home/uname/lib,然后把此文件夹路径写入/etc/ld.so.conf中(并把自己的动态库复制到该文件夹下)。
#ldconfig        //刷新缓存文档/etc/lb.so.cache,使共享设置生效
    然后就可以使用动态库文件libmy.so了。

   
2 动态库文件的使用


2.1 重要的dlfcn.h头文件
    LINUX下使用动态链接库,源程序需要包含dlfcn.h头文件,此文件定义了调用动态链接库的函数的原型。下面详细说明一下这些函数。
   
2.1.1 dlerror
原型为: const char *dlerror(void);
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

2.1.2 dlopen
原型为: void *dlopen (const char *filename, int flag);
dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。
filename: 如果名字不以/开头,则非绝对路径名,将按下列先后顺序查找该文件。
(1) 用户环境变量中的LD_LIBRARY值;
(2) 动态链接缓冲文件/etc/ld.so.cache
(3) 目录/lib,/usr/lib
flag表示在什么时候解决未定义的符号(调用)。取值有两个:
    1) RTLD_LAZY : 表明在动态链接库的函数代码执行时解决。
    2) RTLD_NOW : 表明在dlopen返回前就解决所有未定义的符号,一旦未解决,dlopen将返回错误。
dlopen调用失败时,将返回NULL值,否则返回的是操作句柄。

2.1.3 dlsym : 取函数执行地址
原型为: void *dlsym(void *handle, char *symbol);
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。由此地址,可以带参数执行相应的函数。
如程序代码: void (*add)(int x,int y); /* 说明一下要调用的动态函数add */
add=dlsym("xxx.so","add"); /* 打开xxx.so共享库,取add函数地址 */
add(89,369); /* 带两个参数89和369调用add函数 */

2.1.4 dlclose : 关闭动态链接库
原型为: int dlclose (void *handle);
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

2.2 在程序中使用动态链接库函数

2.2.0

动态库的分为隐式调用和显式
调用两种调用方法。
隐式调用的使用使用方法和静态库的调用差不多,具体方法如下:
    gcc -c -I/home/weil/inc main.c
    gcc -o main1 -L/home/



weil


/lib main.o libmytime.so   //这里是*.so

      在这种调用方式中,需要维护动态链接库的
配置文件/etc/ld.so.conf
来让动态链接库为系统所使用,通常将动态链接库所在目录名追加到动态链接库配置文件中。否则在执行相关的可执行文
件的时候就会出现载入动态链接库失败的现象。

在编译所引用的动态库时,可以在gcc采用
–l或-L选项或直接引用所需的动态链接库方式进行编译。


      在Linux里面,可以采用ldd命令来检查程序依赖共享库。

显式调用


    gcc -o main -ldl main.c

    用gcc编译对应的源文件生成可执行文件,-ldl选项,表示生成的对象模块需要使用共享库。

    在示例程序ady.c中调用动态库libmy.so中的getDate()和getTime()函数,用来显式系统的当前时间。
2.2.1 编写ady.c (本例中使用显示调用的方法)

2.2.2 编写维护文件makefile

   
2.3 编译、运行测试程序
#make
#./ady
可显式系统当前日期、时间。

抱歉!评论已关闭.