当前位置:首页 > 图片 > 视野图片 > 正文
文章正文

linux 添加动态库 Linux下如何解决动态库的链接问题

图片 > 视野图片 > :linux 添加动态库 Linux下如何解决动态库的链接问题是由美文导刊网(www.eorder.net.cn)为您精心收集,如果觉得好,请把这篇文章复制到您的博客或告诉您的朋友,以下是linux 添加动态库 Linux下如何解决动态库的链接问题的正文:

Linux下如何解决动态库的链接问题

静态库是一种以空间换取时间和移植性的做法,一些情况下确实有着一定的意义,但是一些情况下,我们自己编写的简单项目,在绝大多数的机器上不存在移植性问题,是没有必要采用静态编译的。而且,在一些大型项目中,我们很难避免去使用到开源库,举个例子,如果我们只是单纯引用了mysql数据库的几个接口,有必要将整个mysql源文件全部编译吗?代价未免太大。通常的做法,是将mysql的include和lib目录打包之后,一起进行发布,来增强可移植性,也就是今天这里说的动态编译。

但是,动态编译默认情况下,只会去系统默认指定的目录下进行查找lib***.so文件,甚至我们在Makefile中使用-L选项指明了LIB目录,编译不会出错,但在运行的时候,会出现下面这种报错:

/cgi_select: error while loading shared libraries: libmysqlclient.so.18:

cannot open shared object file: No such file or directory(linux 添加动态库)

解决这个问题,网上给出的方法挺多,这里不会全部列出,给出最常用的方法:

1、环境变量。使用export导入环境变量LD_LIBRARY_PATH,指明搜索路径。这个环境变量是临时指定动态库的搜索路径,是绑定终端的,至于什么原因,了解过Linux的同学应该知道,这里不多解释,为了说明问题,这里截图给出,具体用法如下:

(linux 添加动态库)

再次说明,这种做法只是临时生效,在测试的时候为了方便可以使用,但是真正的项目发布,一般不会使用这种做法,因为需要在客户机器上创建环境变量之后才可以运行,我尝试了多种做法,想把命令放到脚本当中自动化去执行,但限于个人能力,尚未跨越子shell这一关。

2、第二种做法就显得更加有效。在/etc/ld.so.conf文件中,指明了动态库的搜索路径,一般请款下,文件内容为

include ld.so.conf.d/*.conf

表明,/etc/ld.so.conf.d目录下的所有*.conf文件中保存的都是动态库的搜索路径。这么说可能不太好理解,进入目录,随意打开一个文件,你就会明白,每个文件中只有一条或几条路径,如下:

[root@bogon ld.so.conf.d]# cat qt-i386.conf

/usr/lib/qt-3.3/lib<br>[root@bogon ld.so.conf.d]

# cat mysql-i386.conf (linux 添加动态库)

每一个工具的动态库,都有着自己的动态库路径,因此,我们可以在该目录下创建自己的*.conf文件,文件中保存自己指定的动态库路径即可,个人绝对,Linux对动态库搜索路径的封装做的真心不错。

当然更改其他*.conf文件或创建自己的动态库连接目录配置文件后,需要使用ldconfig命令使之生效。

[root@bogon ld.so.conf.d]# ldconfig

3、其他的做法就是一些很非主流的做法了,将你所需要的动态库文件直接放入系统默认路径,坦白讲,这样做法没有问题,但是这是在给自己埋地雷,迟早有一天会出大问题。

4、另外还有一种比较生僻的做法,但是开源工程中会用到。使用gcc的选项确实可以实现,-Wl -rpath指定路径,个人来说,很少使用这种做法,gcc/g++是一款很强大的编译工具,提供了上百个选项,有一大部分可能一辈子用不到,用到去查就可以了,没有必要太过深究。

(linux 添加动态库)

本文出自 “暮回” 博客,请务必保留此出处http://muhuizz.blog.51cto.com/11321490/1927864

相关阅读:

返回搜狐,查看更多


一.如何让linux加载当前目录的动态库

linux 加载当前目录的动态库的方法是:设置合适的环境变量LD_LIBRARY_PATH。
设置方法有以下三种:

1、临时修改,log out之后就失效
在terminal中执行:export LD_LIBRARY_PATH=./

2、让当前帐号以后都优先加载当前目录的动态库
修改~/.bash_profile在文件末尾加上两行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH

3、让所有帐号从此都优先加载当前目录的动态库
修改/etc/profile在文件末尾加上两行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH


二.linux 编译是怎么添加动态库的路径

最简单配置就是把连接库目录,添加到/etc/ld.so.conf中,一行一个目录就行,添加完成后,执行#ldco旦长测短爻的诧痊超花nfig更新动态连接库。


三.Linux如何解决动态库的版本控制

(linux 添加动态库)

3.共享库,小版本升级,即接口不变.
当升级小版本时,共享库的soname 是不变的,所以需要重新把soname 的那个连接文件指定新版本就可以。 调用ldconfig命令,系统会帮你做修改那个soname link文件,并把它指向新的版本呢。这时候你的应用程序就自动升级了。
4.共享库,主版本升级,即接口发生变化。
当升级主版本时,共享库的soname 就会加1.比如libhello.so.0.0.0 变为 libhello.so.1.0.0. 这时候再运行ldconfig 文件,就会发现生成两个连接 文件。
ln -s libhello.so.0----libhello.so.0.0.0
ln -s libhello.so.1-----libhello.so.1.0.0
尽管共享库升级,但是你的程序依旧用的是旧的共享库,并且两个之间不会相互影响。
问题是如果更新的共享库只是增加一些接口,并没有修改已有的接口,也就是向前兼容。但是这时候它的主版本号却增加1. 如果你的应用程序想调用新的共享库,该怎么办? 简单,只要手工把soname 文件修改,使其指向新的版本就可以。(这时候ldconfig 文件不会帮你做这样的事,因为这时候soname 和real name 的版本号主板本号不一致,只能手动修改)。
比如: ln -s libhello.so.0 --- libhello.so.1.0.0
但是有时候,主版本号增加,接口发生变化,可能向前不兼容。这时候再这样子修改,就会报错,“xx”方法找不到之类的错误。
总结一下,Linux 系统是通过共享库的三个不同名字,来管理共享库的多个版本。 real name 就是共享库的实际文件名字,soname 就是共享库加载时的用的文件名。在生成共享库的时候,编译器将soname 绑定到共享库的文件头里,二者关联起来。 在应用程序引用共享库时,其通过link name 来完成,link时将按照系统指定的目录去搜索link名字找到共享库,并将共享库的soname写在应用程序的头文件里。当应用程序加载共享库时,就会通过soname在系统指定的目录(path or LD_LIBRARY)去寻找共享库。
当共享库升级时,分为两种。一种是主板本不变,升级小版本和build 号。在这种情况下,系统会通过更新soname( ldconfig 来维护),来使用新的版本号。这中情况下,旧版本就没有用,可以删掉。
另外一种是主版本升级,其意味着库的接口发生变化,当然,这时候不能覆盖已有的soname。系统通过增加一个soname(ldconfig -p 里面增加一项),使得新旧版本同时存在。原有的应用程序在加载时,还是根据自己头文件的旧soname 去寻找老的库文件。
这是一个trick 的地方。第一系统将会在生成库的时候,就没有soname放到库的头里面。从而应用程序连接时候,就把linkname 放到应用程序依赖库里面。或者换句话说就是,soname这时候不带版本号。 有时候有人直接利用这点来升级应用程序,比如,新版本的库,直接拷贝到系统目录下,就会覆盖掉已经存在的旧的库文件,直接升级。 这个给程序员很大程度的便利性,如果一步小心,就会调到类似windows的Dll hell 陷阱里面。建议不要这样做。
【Note】
1. 指定共享库加载的路径。LD_孩珐粉貉莠股疯瘫弗凯LIBRARY_PATH 优先于 path 环境变量。
2. ldd 可以查看程序,或者共享库依赖的库的路径
3. nm 查看共享库暴露的接口
4. ldc......余下全文>>


四.Linux系统中,我已经写好一个动态库,现在想将一个a.o文件重新加入动态库可以吗?

静态库.a可以,动态库.so不可以。


五.linux动态库和静态库的区别

  根据链接时期的不同,库又有:静态库和共享库(动态库)
  二者的不同点在于代码被载入的发亥篡酵诂寂磋檄单漏时刻不同
  静态库的代码在编译过程中已经被载入可执行程序,因此体积较大
  共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。


六.linux下的静态库创建与查看,及如何查看某个可执行依赖于哪些动态库

创建静态库:
ar -rcs test.a *.o
查看静态库:
ar -tv test.a
解压静态库:
ar -x test.a

查看程序依赖的动态库:
readelf -a xxx|grep library<辅珐滇貉鄄股殿瘫东凯br />如:可以看到,下面的交叉程序hello执行依赖于如下两个动态库。
rebi@ubuntu:~/test$ arm-none-linux-gnueabi-readelf -a hello|grep "library"
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.6]
rebi@ubuntu:~/test$

或者:readelf -l hello 即可。

nm xxx 查看符号
其中,T表示代码段,U表示在其它地方定义,所以需要确保必须在某个.o或库里被定义过。


七.linux怎样添加永久动态库环境变量

/etc/ld.so.conf文件里增加动态库所在的路径
或者/etc/l虎旦港秆蕃飞歌时攻江d.so.conf.d下新建.conf文件,内容为加动态库所在的路径


八.如何查看linux动态链接库文件的版本等其他信息

ldd <可执行文件名> 查看可执行文件链接了哪些
系统动态链接库
nm <可执行文件名>
查看可执行文件里面有哪些符号
strip <可执行文件名>
去除符号表可以给可执行文件瘦身
如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令
strings
<可执行文件名>

Linux操作系统上面的动态共享库大致分为三类:

1、操作系统级别的共享库和基础的系统工具库

比方说libc.so, libz.so,
libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/l缉花光拘叱饺癸邪含矛ib64和/usr
/lib64目录。如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6
/lib64目录。此外还可能有其他特定Linux版本的系统库目录。

这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。

2、应用程序级别的系统共享库

并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib和/usr/local/lib64这两个目录下面。很多你自行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local
/lib下面去寻找共享库。

以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。这是为什么呢?因为以上这些目录默认就被加入到动态链接程序的搜索路径里面了。Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。这个文件的内容格式大致如下:

/usr/X11R6/lib64
/usr/X11R6/lib
/usr/local/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/ImageMagick/lib

假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用
ImageMagick的动态共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig
命令即可。

ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。为了确认ldconfig已经搜索到ImageMagick的库,我们可以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:

strings
/etc/ld.so.cach......余下全文>>


九.linux的动态库.so文件放下哪里

这个一般没有要求。一般/lib /usr/lib
其它的要看具体情况。。。如果你是自己编译的应用程序,.so文件一般就在安装目录下的lib目录中。


十.linux动态库和静态库的区别

两者区别:
a,静态库的使用需要:
1 包含一个对应的头文件告知编译器lib文件里面的具体内容
2 设置lib文件允许编译器去查找已经编译好的二进制代码

b,动态库的使用:
程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库

c,依赖性:
静态链接表示静态性,在编译链接之后, lib库中需要的资源已经在可执行程序中了, 也就是静态存在,没有依赖性了
动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供 需要的 动态库,有依赖性, 运行时候没有找到库就不能运行了

d,区别:
简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。
做成静态库可执行文件本身比较大,但不必附带动态库
做成动态库可执行文件本身比较小,但需要附带动态库
链接静态库,编译的可执行文件比较大,当然可以用strip命令精简一下(如:strip libtest.a),但还是要比链接动态库的可执行文件大。程序运行时间速度稍微快一点。
静态库是程序运行的时候已经调入内存,不管有没有调用,都会在内存里头。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
其在编译程序时若链接,程序运行时会在系统指定的路径下搜索,然后导入内存,程序一般执行时间稍微长一点,但编译的可执行文件比较小;动态库是程序运行的时候需要调用的时候才装入内存,不需要的时候是不会装入内存的。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

动态链接库的特点与优势

首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:

1. 可以实现进程之间的资源共享。

什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝笭互蒂就郦脚垫协叮茅;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。

2. 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。

3. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。

程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。

静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。
动态库:在目标文件运行时加载,手动加载,且对库有依赖性。

具体在开发中用到哪种库,我觉得还是根据实际的内存大小,ROM大小,运行的速度等综合考虑。...余下全文>>

  • linux找不到动态库 Linux下动态库和静态库的制作及使用
  • linux 动态库 链接 Linux下如何解决动态库的链接问题
  • linux 添加动态库 Linux下如何解决动态库的链接问题由美文导刊网(www.eorder.net.cn)收集整理,转载请注明出处!原文地址http://www.eorder.net.cn/pic60243/

    文章评论
    Copyright © 2006 - 2016 www.eorder.net.cn All Rights Reserved
    美文导刊网 版权所有