`
steven-zhou
  • 浏览: 206623 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

理解动态链接库

阅读更多
在Linux的应用开发中,静态库和动态库都是我们经常用到的技术,有必要对这两个概念及其原理做一些介绍。

静态库
静态库是一些目标文件的集合,通常为后缀为.o 的文件,通过ar 工具打包而成,命名
格式为libxxx.a ,其中xxx 为给定的静态库文件名,如libm.a ,为数学函数库,用户也可以命名自己的库。在创建可执行程序的过程中,静态库同时被链接到程序代码,被主程序调用的函数目标文件连同主程序组合成单一的可执行程序。静态库只在程序链接时起作用,最终的执行程序脱离静态库运行。

动态库
按照其英文(shared library )也可理解为共享库,动态库的后缀一般为.so ,通过编译器生成,在不同的平台有不同的生成方法,但是在Linux 平台中,其使用及工作原理是一致的。使用动态库创建执行程序,分为两个阶段:链接阶段,即通过ld 创建执行程序时,链接编辑器会在指定的动态库中搜索、解析被主程序调用的函数及其他变量等,如引用被找到,则在执行程序的XCOFF 头结构的loader 区域,建立包含引用的动态库的影像,反之,如在指定的动态库中没有找到此引用的定义,编译器会给出类似未定义的符号引用错误。这不同于静态库,包含引用的目标文件并不和执行程序链接在一起。
另一阶段为运行阶段,即执行程序运行时。程序运行时,系统相关模块将读取定义执行程
序的XCOFF 头结构中的信息,查找并加载相关的动态库,假设,所有被应用的动态库都被定位且加载后,程序将开始运行。反之,如果,被应用的动态库丢失,则程序报错。这一个过程我们常称之为动态链接。可以通过一个简单的例子来分析静态库与动态库的不同,假定执行程序名为a.out ,分别通过静态库和动态库编译、链接.对使用动态库的程序,程序启动后,相关的动态库的目标代码加载到系统内存,而且可以被其他使用此动态库的执行程序共享使用。这样,在给定的时间,统一动态库的代码在系统中只有一份拷贝,所有使用此动态库的程序可共享这一拷贝。动态链接的使用可以节省系统内存的使用,对一些比较复杂的应用作用比较明显,另外,执行程序代码的减小,也可以节省磁盘空间。

加载动态链接库,首先为共享库分配物理内存,然后在进程对应的页表项中建立虚拟页和物理页面之间的映射。你可以认为系统中存在一种引用计数机制,每当一个进程加载了共享库(在该进程的页表中进行一次映射),引用计数加一;一个进程显式卸载(通过dlclose等)共享库或进程退出时,引用计数减一,当减少到0时,系统卸载共享库。

(1)打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag); dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。

(2)取函数执行地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol); dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。

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

(4)动态库错误函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

在取到函数执行地址后,就可以在动态库的使用程序里面根据动态库提供的函数接口声明调用动态库里面的函数。在编写调用动态库的程序的makefile文件时,需要加入编译选项-rdynamic和-ldl。


用nm命令查看动态库文件提供哪些调用:
nm -D /usr/lib/libz.so
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics