您的位置:首页 > 运维架构 > Linux

Linux库文件知识总结

2014-10-30 17:14 183 查看
Linux库文件知识

基本知识

库文件是一组预先编译好的函数集合,这些函数都是按照可重用的原则编写的。

库文件一般存在于/lib和/usr/lib目录中

库文件一般以lib开头

.a代表静态库

创建静态库:ar crv libfoo.a bill.o
fred.o

部分系统创建好了静态库后需要创建一个内容表:ranlib libfoo.a

解压静态库:ar x libfoo.a,可以将一个.a解压成多个.o,用于合并多个静态库。

.so代表动态库(共享库,类似于Windows的dll),它在linux中也叫做共享库

动态库在编译时加上-shared选项来创建

动态库名真正的库一般以libm.so.N来表示,最后一个N代表主版本号,一般使用固定文件名如libm.so链接到库的最新版本,这样可以实现库的动态升级,并且可以看到版本号。

使用ldd可以查看到程序需要的动态库。

使用库文件

直接使用路径引用:gcc -o fred fred.c /usr/lib/libm.a

使用简称引用,库文件需要在库路径下:gcc -o fred fred.c -lm:-l[库名]相当于引用库路径下的lib[库名].a或者lib[库名].so

增加库路径:gcc -o fred fred.c -L./libs -lm

库的依赖

gcc对于库的加载是从后往前进行的,因此,最基础(最被依赖)的库应该放在后面。

使用动态库

使用dlopen、dlsym、dlclose操作.so文件。可以打开库文件,读取库中的函数或者其他变量数据。(TODO:dlsym读取符号失败后会返回NULL,那么dlerror()会不会返回错误信息?是否读取到的dlerror()为NULL就代表dlsym执行成功了?也就是,如何确定dlsym是否执行成功?)

dlopen:打开动态链接库,成功返回动态链接库的索引ID,失败返回NULL。

dlsym:解析动态链接库中的符号资源,成功返回函数指针或者全局变量指针。

dlerror:返回动态链接库的出错信息,如果成功,返回NULL。

查看库中的信息

使用nm查看程序或者库中包含的函数

Linux软件从源代码安装的3个步骤,这也是大部分库的生成方法

./configure

--prefix=/home/user/local   #自定义安装路径

--prefix=$HOME   #当用户不是root用户时,需要安装软件到自己可写的目录,则使用这条语句进行配置,可以在make完成后将软件安装到用户目录。

make

make install

库路径

查找顺序介绍: http://blog.csdn.net/xuzhihong_gdut/article/details/3836262

动态库的安装

放入/use/lib或者其他的默认库路径中即可,注意32位和64位的区别,库路径存放于:/etc/ld.so.conf

或者将路径放到环境变量LD_LIBRARY_PATH中。

执行ldconfig重载库。

注意:如果需要其他用户使用这个库文件,需要给库文件加上读权限,否则会提示:cannot open shared object file: Permission denied

如果同时存在动态库和静态库,默认情况下会优先使用动态库

-static  在链接时强制使用静态库

--static-libgcc    链接静态libgcc库(其他库这样使用无效)

--shared-libgcc   链接动态libgcc库

指定特定库链接为动态库或者静态库

在动态库前加上-Bdynamic

在静态库前加上-Bstatic

-Wl,-dn后面是静态链接-Wl,-dy后面是动态连接

cc -g -o test_server  main_server.o main_db.o err_me.o -Wl,-dn -L/usr/local/mysql/lib/ -lmysqlclient  -Wl,-dy -lpthread -lm -ldl -lcrypt

库版本

设计库的时候,如果需要匹配库版本与头文件,可以在头文件中使用库版本作为一个变量名,在cpp文件中定义这个变量名,在头文件中声明这个变量名。如果库与头文件不一致,则编译期间会提示找不到变量。

头文件:

#define SESSION_API_VER 1_0_0

 

#ifdef GET_STR

#undef GET_STR

#endif // GET_STR

#define GET_STR(tempname) #tempname

 

#ifdef TO_STR

#undef TO_STR

#endif // TO_STR

#define TO_STR(tempname) GET_STR(tempname)

 

#ifdef TEXTCAT

#undef TEXTCAT

#endif // TEXTCAT

#define TEXTCAT(text1,text2) text1##text2

 

#ifdef TEXTCAT2

#undef TEXTCAT2

#endif // TEXTCAT2

#define TEXTCAT2(text1,text2) TEXTCAT(text1,text2)

Cpp文件:

string TEXTCAT2(V, SESSION_API_VER) = TO_STR(SESSION_API_VER);

静态库和动态库的优缺点?动态库和静态库的优缺点,这里只讲优点,优点即是对方的缺点。

动态库的优点:

可以动态替换升级而不改变依赖它的程序,也就是说,程序无需重新编译。

可以作为框架程序的一项扩展,提高扩展性,让其他开发者按照指定的接口开发自己的动态库。

可多个程序共享,降低程序大小。

如上一个问题,可以避免多个库同名函数的冲突。

静态库的优点:

省去一项加载耗时。

大量发布时比较方便,无需加载各种依赖的动态库。

避免了一些动态库兼容问题,比如动态库版本不对导致程序运行异常,提高可控性。

适用于一些无root权限的机器发布,如果安装动态库,需要root权限。

如何选择?

可以根据上述优点,在不同的场合使用不同的库。

为便于可控,在后台服务中,个人比较喜欢使用静态库。

2个库中函数名冲突的解决办法:

可使用动态库的解决方法:可以使用动态库封装2个静态库,程序只加载动态库。

具体动态库为什么可以屏蔽符号名,可能与链接静态库时会寻找符号名写入程序有关,具体细节作为遗留问题再研究研究

不可使用动态库的解决方法:

有库的源文件

修改其中一个库文件的冲突函数。

给其中一个库加入命名空间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: