#参考:
# 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
可显式系统当前日期、时间。

更多相关文章

  1. Linux环境下注册函数的调用顺序
  2. Linux-自己创建动态库静态库
  3. linux线程函数中代替sleep的方法
  4. Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、si
  5. Linux下cfsetospeed和cfsetispeed函数
  6. Linux FFmpeg 编译so动态库
  7. 字符串处理函数strcat和strtok
  8. Linux的时间函数(转载)
  9. Linux下动态链接库创建问题

随机推荐

  1. NETBEAN 开发Android应用
  2. Android 线性布局(LinearLayout)内各控件
  3. 线性布局和相对布局
  4. ListView背景修饰
  5. FrameLayout的使用
  6. android客户端和servlet服务端的简单登录
  7. android-android.hardware.Camera
  8. CountDownLatch
  9. 如何在你的本上或者pc上运行 Android [翻
  10. Android(安卓)Resource Framework