
[导读]本文仅讨论linux下的库。 一口君中学阶段最喜欢的一首歌。 窦仙才华横溢、潇洒不羁、与世无争,酷的外焦里嫩! 让我们随着窦仙高昂的声音来学习什么是(酷)库吧! 在windows平台和linux平台下都大量存在着库。一般是软件作者为了发布方便、替换方便或二次开发目的,而发布的一组可以单独与应用程序进行compile time或runtime链接的二进制可重定位目标码文件。 本质上来说库是一种可执行代码的二进制形式,这个文件可以在编译时由编译器直接链接到可执行程序中,也可以在运行时由操作系统的runtime enviroment根据需要动态加载到内存中。 一组库,就形成了一个发布包,当然,具体发布多少个库,完全由库提供商自己决定。 由于windows和linux的本质不同,因此二者库的二进制是不兼容的。 现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。 共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。 本文仅讨论linux下的库。 二、库的分类库有两种:静态库和共享库(动态库)。 win32平台下,静态库通常后缀为.lib,动态库为.dll]int add(int x,int y){ return x+y; } int sub(int x,int y) { return x-y; } add.h <span]<span]gcc -c add.c
#include "add.h" void main() { printf("add(5,4) is %d\n",add(5,4)); printf("sub(5,4) is %d\n",sub(5,4)); } 静态库的文件可以放在任意的位置,编译时只需要找到该库文件即可。 gcc]gcc -c -I /home/xxxx/include test.c //假设test.c要使用对应的静态库gcc -o test -L /home/xxxxx/lib test.o libadd.a 或者 gcc]gcc -fPIC -o libadd.o -c add.cgcc -shared -o libadd.so libadd.o 也可以直接使用一条命令 gcc]sudo cp libadd.so /lib
注意观察编译时动态库的名字与库文件对应关系 libadd.so<--------->-ladd[p=26,]libadd.so<--------->-ladd [p=26,] void * dlopen(const char *filename, int flag); 参数 filename 如果文件名filename是以“/”开头,也就是使用绝对路径,那么dlopne就直接使用它,而不去查找某些环境变量或者系统设置的函数库所在的目录了。否则dlopen()就会按照下面的次序查找函数库文件: 1. 环境变量LD_LIBRARY指明的路径。 2. /etc/ld.so.cache中的函数库列表。 3. /lib目录,然后/usr/lib。 一些很老的a.out的loader则是采用相反的次序,也就是先查 /usr/lib,然后是/lib。 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'。 返回值 dlopen()函数的返回值是一个句柄,然后后面的函数就通过使用这个句柄来做进一步的操作。如果打开失败dlopen()就返回一个NULL。如果一个函数库被多次打开,它会返回同样的句柄。 如果有好几个函数库,它们之间有一些依赖关系的话,例如X依赖Y,那么你就要先加载那些被依赖的函数。例如先加载Y,然后加载X。 dlerror() 通过调用dlerror()函数,我们可以获得最后一次调用dlopen(),dlsym(),或者dlclose()的错误信息。 dlsym() 如果你加载了一个DL函数库而不去使用当然是不可能的了,使用一个DL函数库的最主要的一个函数就是dlsym(),这个函数在一个已经打开的函数库里面查找给定的符号。这个函数如下定义: ]参数handle 就是由dlopen打开后返回的句柄, symbol 是一个以NIL结尾的字符串。 功能: 如果dlsym()函数没有找到需要查找的symbol,则返回NULL。如果你知道某个symbol的值不可能是NULL或者0,那么就很好,你就可以根据这个返回结果判断查找的symbol是否存在了;不过,如果某个symbol的值就是NULL,那么这个判断就有问题了。标准的判断方法是先调用dlerror(),清除以前可能存在的错误,然后调用dlsym()来访问一个symbol,然后再调用dlerror()来判断是否出现了错误。 dlclose() dlopen()函数的反过程就是dlclose()函数,dlclose()函数用力关闭一个DL函数库。Dl函数库维持一个资源利用的计数器,当调用dlclose的时候,就把这个计数器的计数减一,如果计数器为0,则真正的释放掉。真正释放的时候,如果函数库里面有_fini()这个函数,则自动调用_fini()这个函数,做一些必要的处理。Dlclose()返回0表示成功,其他非0值表示错误。 举例 <span]<span] vi /etc/profile在文件里末尾加上对应的环境变量信息。 动态库环境变量设置: <span]<span]source /etc/profile3./etc/ld.so.conf 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径 vim]/usr/local/lib/运行ldconfig,该命令会重建/etc/ld.so.cache文件 七、常见库的移植1.jpeg库,用于jpeg图像处理下载地址: http://www.ijg.org/files/ 解压 tar]./configure --host=arm-linux-gnueabihf --prefix=$PWD/temp_install编译, 安装 ] mkdir -p /home/peng/jpeg-6b/temp_install/includemkdir -p /home/peng/jpeg-6b/temp_install/lib mkdir -p /home/peng/jpeg-6b/temp_install/man/man1 |