- 浏览: 584727 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
JamAndVariousAbalone:
存储方式的不同吧。gb_tree是平衡树,list是线性结构。 ...
gb_trees和lists的访问效率相差很大 -
genesislive:
eporf:analyse()写错了,应该改成eprof:an ...
Erlang程序的性能测试工具(1) -
vampirezh:
高手啊 求带 ! 请列出带徒标准
Erlang的未来(2008) -
aiquantong:
great!
rebar工具使用备忘录 (1) -
wccxiaoan:
basho的资源 都没办法打开,不过还是有帮助,谢谢。
关于webmachine
原文:http://blog.chinaunix.net/u/16651/showart.php?id=434959
众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后,一般都复制到这两个目录中。当程序执行时需要某动态库,并且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,然后加载该文件到内存中,这样程序就可以使用该动态库中的函数,以及该动态库的其它资源了。在Linux中,动态库的搜索路径除了默认的搜索路径外,还可以通过以下三种方法来指定。
方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。
可以通过编辑配置文件/etc/ld.so.conf来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次编辑完该文件后,都必须运行命令ldconfig使修改后的配置生效。我们通过例1来说明该方法。
例1:
我们通过以下命令用源程序pos_conf.c(见程序1)来创建动态库 libpos.so,详细创建过程请参考文[1]。
# gcc -c pos_conf.c
# gcc -shared -fPCI -o libpos.so pos_conf.o
#
程序1: pos_conf.c
接着通过以下命令编译main.c(见程序2)生成目标程序pos。
# gcc -o pos main.c -L. -lpos
程序2: main.c
然后把库文件移动到目录/root/test/conf/lib中。
# mkdir -p /root/test/conf/lib
# mv libpos.so /root/test/conf/lib
最后编辑配置文件/etc/ld.so.conf,在该文件中追加一行"/root/test/conf/lib"。
运行程序pos试试。
# ./pos
./pos: error while loading shared libraries: libpos.so: cannot open shared object file: No such file or directory
出错了,系统未找到动态库libpos.so。找找原因,原来在编辑完配置文件/etc/ld.so.conf后,没有运行命令ldconfig,所以刚才的修改还未生效。我们运行ldconfig后再试试。
# ldconfig
# ./pos /root/test/conf/lib
程序pos运行成功,并且打印出正确结果。
方法二:通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(!)。
通过设定环境变量LD_LIBRARY_PATH也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔。
不过LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。(LD_LIBRARY_PATH的缺陷和使用准则,可以参考《Why LD_LIBRARY_PATH is bad》 )。通常情况下推荐还是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路 径查找库,避免了使用LD_LIBRARY_PATH环境变量查找。
下面通过例2来说明本方法。
例2:
我们通过以下命令用源程序pos_env.c(见程序3)来创建动态库libpos.so。
# gcc -c pos_env.c
# gcc -shared -fPCI -o libpos.so pos_env.o
程序3: pos_env.c
测试用的可执行文件pos可以使用例1中的得到的目标程序pos,不需要再次编译。因为pos_conf.c中的函数pos和pos_env.c中的函数pos 函数原型一致,且动态库名相同,这就好比修改动态库pos后重新创建该库一样。这也是使用动态库的优点之一。
然后把动态库libpos.so移动到目录/root/test/conf/lib中。
# mkdir -p /root/test/env/lib
# mv libpos.so /root/test/env/lib
我们可以使用export来设置该环境变量,在设置该环境变量后所有的命令中,该环境变量都有效。
例如:
# export LD_LIBRARY_PATH=/root/test/env/lib
但本文为了举例方便,使用另一种设置环境变量的方法,既在命令前加环境变量设置,该环境变量只对该命令有效,当该命令执行完成后,该环境变量就无效了。如下述命令:
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /root/test/env/lib
程序pos运行成功,并且打印的结果是"/root/test/env/lib",正是程序pos_env.c中的函数pos的运行结果。因此程序pos搜索到的动态库是/root/test/env/lib/libpos.so。
方法三:在编译目标代码时指定该程序的动态库搜索路径。
还可以在编译目标代码时指定程序的动态库搜索路径。这是通过gcc 的参数"-Wl,-rpath,"指定(如例3所示)。当指定多个动态库搜索路径时,路径之间用冒号":"分隔。
例3:
我们通过以下命令用源程序pos.c(见程序4)来创建动态库libpos.so。
# gcc -c pos.c
# gcc -shared -fPCI -o libpos.so pos.o
程序4: pos.c
因为我们需要在编译目标代码时指定可执行文件的动态库搜索路径,所以需要用gcc命令重新编译源程序main.c(见程序2)来生成可执行文件pos。
# gcc -o pos main.c -L. -lpos -Wl,-rpath,./
再运行程序pos试试。
# ./pos ./
程序pos运行成功,输出的结果正是pos.c中的函数pos的运行结果。因此程序pos搜索到的动态库是./libpos.so。
以上介绍了三种指定动态库搜索路径的方法,加上默认的动态库搜索路径/lib和/usr/lib,共五种动态库的搜索路径,那么它们搜索的先后顺序是什么呢?
在 介绍上述三种方法时,分别创建了动态库./libpos.so、 /root/test/env/lib/libpos.so和/root/test/conf/lib/libpos.so。我们再用源程序 pos_lib.c(见程序5)来创建动态库/lib/libpos.so,用源程序pos_usrlib.c(见程序6)来创建动态库 /usr/lib/libpos.so。
这样我们得到五个动态库libpos.so,这些动态库的名字相同,且都包含相同函数原型的公用函数pos。但存储的位置不同和公用函数pos打印的结果不同。每个动态库中的公用函数pos都输出该动态库所存放的位置。这样我们可以通过执行例3中的可执行文件pos得到的结果不同获知其搜索到了 哪个动态库,从而获得第1个动态库搜索顺序,然后删除该动态库,再执行程序pos,获得第2个动态库搜索路径,再删除第2个被搜索到的动态库,如此往复, 将可得到Linux搜索动态库的先后顺序。程序pos执行的输出结果和搜索到的动态库的对应关系如表1所示: 程序pos输出结果 使用的动态库 对应的动态库搜索路径指定方式
./ ./libpos.so 编译目标代码时指定的动态库搜索路径
/root/test/env/lib /root/test/env/lib/libpos.so 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
/root/test/conf/lib /root/test/conf/lib/libpos.so 配置文件/etc/ld.so.conf中指定的动态库搜索路径
/lib /lib/libpos.so 默认的动态库搜索路径/lib
/usr/lib /usr/lib/libpos.so 默认的动态库搜索路径/usr/lib
表1: 程序pos输出结果和动态库的对应关系
创建各个动态库,并放置在相应的目录中。测试环境就准备好了。执行程序pos,并在该命令行中设置环境变量LD_LIBRARY_PATH。
# LD_LIBRARY_PATH=/root/test/env/lib ./pos ./
根据程序pos的输出结果可知,最先搜索的是编译目标代码时指定的动态库搜索路径。然后我们把动态库./libpos.so删除了,再运行上述命令试试。
# rm libpos.so
rm: remove regular file `libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /root/test/env/lib
根据程序pos的输出结果可知,第2个动态库搜索的路径是环境变量LD_LIBRARY_PATH指定的。我们再把/root/test/env/lib/libpos.so删除,运行上述命令。
# rm /root/test/env/lib/libpos.so
rm: remove regular file `/root/test/env/lib/libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /root/test/conf/lib
第3个动态库的搜索路径是配置文件/etc/ld.so.conf指定的路径。删除动态库/root/test/conf/lib/libpos.so后再运行上述命令。
# rm /root/test/conf/lib/libpos.so
rm: remove regular file `/root/test/conf/lib/libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /lib
第4个动态库的搜索路径是默认搜索路径/lib。我们再删除动态库/lib/libpos.so,运行上述命令。
# rm /lib/libpos.so
rm: remove regular file `/lib/libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /usr/lib
最后的动态库搜索路径是默认搜索路径/usr/lib。
综合以上结果可知,动态库的搜索路径搜索的先后顺序是:
1.编译目标代码时指定的动态库搜索路径;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4.默认的动态库搜索路径/lib;
5.默认的动态库搜索路径/usr/lib。
在上述1、2、3指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的。对此本文不再举例说明,有兴趣的读者可以参照本文的方法验证。
众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后,一般都复制到这两个目录中。当程序执行时需要某动态库,并且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,然后加载该文件到内存中,这样程序就可以使用该动态库中的函数,以及该动态库的其它资源了。在Linux中,动态库的搜索路径除了默认的搜索路径外,还可以通过以下三种方法来指定。
方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。
可以通过编辑配置文件/etc/ld.so.conf来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次编辑完该文件后,都必须运行命令ldconfig使修改后的配置生效。我们通过例1来说明该方法。
例1:
我们通过以下命令用源程序pos_conf.c(见程序1)来创建动态库 libpos.so,详细创建过程请参考文[1]。
# gcc -c pos_conf.c
# gcc -shared -fPCI -o libpos.so pos_conf.o
#
#include <stdio.h> void pos() { printf("/root/test/conf/lib\n"); }
程序1: pos_conf.c
接着通过以下命令编译main.c(见程序2)生成目标程序pos。
# gcc -o pos main.c -L. -lpos
void pos(); int main() { pos(); return 0; }
程序2: main.c
然后把库文件移动到目录/root/test/conf/lib中。
# mkdir -p /root/test/conf/lib
# mv libpos.so /root/test/conf/lib
最后编辑配置文件/etc/ld.so.conf,在该文件中追加一行"/root/test/conf/lib"。
运行程序pos试试。
# ./pos
./pos: error while loading shared libraries: libpos.so: cannot open shared object file: No such file or directory
出错了,系统未找到动态库libpos.so。找找原因,原来在编辑完配置文件/etc/ld.so.conf后,没有运行命令ldconfig,所以刚才的修改还未生效。我们运行ldconfig后再试试。
# ldconfig
# ./pos /root/test/conf/lib
程序pos运行成功,并且打印出正确结果。
方法二:通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(!)。
通过设定环境变量LD_LIBRARY_PATH也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔。
不过LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。(LD_LIBRARY_PATH的缺陷和使用准则,可以参考《Why LD_LIBRARY_PATH is bad》 )。通常情况下推荐还是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路 径查找库,避免了使用LD_LIBRARY_PATH环境变量查找。
下面通过例2来说明本方法。
例2:
我们通过以下命令用源程序pos_env.c(见程序3)来创建动态库libpos.so。
# gcc -c pos_env.c
# gcc -shared -fPCI -o libpos.so pos_env.o
#include <stdio.h> void pos() { printf("/root/test/env/lib\n"); }
程序3: pos_env.c
测试用的可执行文件pos可以使用例1中的得到的目标程序pos,不需要再次编译。因为pos_conf.c中的函数pos和pos_env.c中的函数pos 函数原型一致,且动态库名相同,这就好比修改动态库pos后重新创建该库一样。这也是使用动态库的优点之一。
然后把动态库libpos.so移动到目录/root/test/conf/lib中。
# mkdir -p /root/test/env/lib
# mv libpos.so /root/test/env/lib
我们可以使用export来设置该环境变量,在设置该环境变量后所有的命令中,该环境变量都有效。
例如:
# export LD_LIBRARY_PATH=/root/test/env/lib
但本文为了举例方便,使用另一种设置环境变量的方法,既在命令前加环境变量设置,该环境变量只对该命令有效,当该命令执行完成后,该环境变量就无效了。如下述命令:
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /root/test/env/lib
程序pos运行成功,并且打印的结果是"/root/test/env/lib",正是程序pos_env.c中的函数pos的运行结果。因此程序pos搜索到的动态库是/root/test/env/lib/libpos.so。
方法三:在编译目标代码时指定该程序的动态库搜索路径。
还可以在编译目标代码时指定程序的动态库搜索路径。这是通过gcc 的参数"-Wl,-rpath,"指定(如例3所示)。当指定多个动态库搜索路径时,路径之间用冒号":"分隔。
例3:
我们通过以下命令用源程序pos.c(见程序4)来创建动态库libpos.so。
# gcc -c pos.c
# gcc -shared -fPCI -o libpos.so pos.o
#include <stdio.h> void pos() { printf("./\n"); }
程序4: pos.c
因为我们需要在编译目标代码时指定可执行文件的动态库搜索路径,所以需要用gcc命令重新编译源程序main.c(见程序2)来生成可执行文件pos。
# gcc -o pos main.c -L. -lpos -Wl,-rpath,./
再运行程序pos试试。
# ./pos ./
程序pos运行成功,输出的结果正是pos.c中的函数pos的运行结果。因此程序pos搜索到的动态库是./libpos.so。
以上介绍了三种指定动态库搜索路径的方法,加上默认的动态库搜索路径/lib和/usr/lib,共五种动态库的搜索路径,那么它们搜索的先后顺序是什么呢?
在 介绍上述三种方法时,分别创建了动态库./libpos.so、 /root/test/env/lib/libpos.so和/root/test/conf/lib/libpos.so。我们再用源程序 pos_lib.c(见程序5)来创建动态库/lib/libpos.so,用源程序pos_usrlib.c(见程序6)来创建动态库 /usr/lib/libpos.so。
#include <stdio.h> void pos() { printf("/lib\n"); }程序5: pos_lib.c
#include <stdio.h> void pos() { printf("/usr/lib\n"); }程序6: pos_usrlib.c
这样我们得到五个动态库libpos.so,这些动态库的名字相同,且都包含相同函数原型的公用函数pos。但存储的位置不同和公用函数pos打印的结果不同。每个动态库中的公用函数pos都输出该动态库所存放的位置。这样我们可以通过执行例3中的可执行文件pos得到的结果不同获知其搜索到了 哪个动态库,从而获得第1个动态库搜索顺序,然后删除该动态库,再执行程序pos,获得第2个动态库搜索路径,再删除第2个被搜索到的动态库,如此往复, 将可得到Linux搜索动态库的先后顺序。程序pos执行的输出结果和搜索到的动态库的对应关系如表1所示: 程序pos输出结果 使用的动态库 对应的动态库搜索路径指定方式
./ ./libpos.so 编译目标代码时指定的动态库搜索路径
/root/test/env/lib /root/test/env/lib/libpos.so 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
/root/test/conf/lib /root/test/conf/lib/libpos.so 配置文件/etc/ld.so.conf中指定的动态库搜索路径
/lib /lib/libpos.so 默认的动态库搜索路径/lib
/usr/lib /usr/lib/libpos.so 默认的动态库搜索路径/usr/lib
表1: 程序pos输出结果和动态库的对应关系
创建各个动态库,并放置在相应的目录中。测试环境就准备好了。执行程序pos,并在该命令行中设置环境变量LD_LIBRARY_PATH。
# LD_LIBRARY_PATH=/root/test/env/lib ./pos ./
根据程序pos的输出结果可知,最先搜索的是编译目标代码时指定的动态库搜索路径。然后我们把动态库./libpos.so删除了,再运行上述命令试试。
# rm libpos.so
rm: remove regular file `libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /root/test/env/lib
根据程序pos的输出结果可知,第2个动态库搜索的路径是环境变量LD_LIBRARY_PATH指定的。我们再把/root/test/env/lib/libpos.so删除,运行上述命令。
# rm /root/test/env/lib/libpos.so
rm: remove regular file `/root/test/env/lib/libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /root/test/conf/lib
第3个动态库的搜索路径是配置文件/etc/ld.so.conf指定的路径。删除动态库/root/test/conf/lib/libpos.so后再运行上述命令。
# rm /root/test/conf/lib/libpos.so
rm: remove regular file `/root/test/conf/lib/libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /lib
第4个动态库的搜索路径是默认搜索路径/lib。我们再删除动态库/lib/libpos.so,运行上述命令。
# rm /lib/libpos.so
rm: remove regular file `/lib/libpos.so'? y
# LD_LIBRARY_PATH=/root/test/env/lib ./pos /usr/lib
最后的动态库搜索路径是默认搜索路径/usr/lib。
综合以上结果可知,动态库的搜索路径搜索的先后顺序是:
1.编译目标代码时指定的动态库搜索路径;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4.默认的动态库搜索路径/lib;
5.默认的动态库搜索路径/usr/lib。
在上述1、2、3指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的。对此本文不再举例说明,有兴趣的读者可以参照本文的方法验证。
发表评论
-
静态链接与动态链接
2014-09-06 03:24 1576基于gmp开发第三方库,后者以动态链接库(静态库?)对方式发布 ... -
在macbook上安装linux
2014-06-12 10:29 23061. 安装最新的rEFInd > 0.8.2 http: ... -
关于nif
2013-08-19 10:28 5230一、NIF的误用问题 使用NIF是很危险的,一不小心它就会搞 ... -
遇到的riak性能问题
2013-07-23 10:59 24581。 遇到一个奇怪的性能问题,多个进程中用riakc_pb_ ... -
dialyzer使用备忘
2013-07-04 12:36 1661一、构建PLT文件: 新构建 dialyzer --build ... -
手工从源码制作一个riak安装包
2013-06-22 18:47 1680riak的Makefile文件提供了各个平台上的安装包的生成脚 ... -
folsom_metrics使用备忘
2013-06-07 15:41 1501folsom是一个通用的统计度量工具。使用很简单,关键是搞清它 ... -
git 库永久删除大文件
2013-01-08 11:49 4747无意中把一个装有很多大文件数据的文件夹(./my1202260 ... -
Riak Core与folsom
2012-09-01 11:54 1525folsom是Riak从1.2开始引入。 -
关于Erlang/OTP的application参数配置
2012-08-26 23:27 9181Erlang/OTP中将完成特定功能的一组模块组织起来,称之 ... -
rebar工具使用备忘录 (5)
2012-08-23 18:17 1529haogongju、人人IT网、59n南龙、360doc、as ... -
lager的使用
2012-08-23 15:06 10603haogongju、人人IT网、59n南龙、360doc不要抄 ... -
rebar工具使用备忘录 (4)
2012-08-22 19:20 5663haogongju、人人IT网、59n南龙、360doc、as ... -
rebar工具使用备忘录 (3)
2012-08-22 19:18 1335haogongju、人人IT网、59n南龙、360doc不要抄 ... -
对Riak Core的探索 (9) cheatsheet
2012-08-12 12:58 1704haogongju、人人IT网、59n南龙、360doc不要抄 ... -
对Riak Core的探索 (8)
2012-08-11 18:52 1276haogongju、人人IT网、59n南龙、360doc不要抄 ... -
对Riak Core的探索 (7)
2012-08-10 18:15 1387haogongju、人人IT网、59n南龙、360doc不要抄 ... -
对Riak Core的探索 (6) HTTP接口
2012-08-09 16:16 1560haogongju,人人IT网,360do ... -
对Riak Core的探索 (5) 业务逻辑的实现:数据如何处理
2012-08-07 18:18 1678业务逻辑的实现:数据 ... -
对riak_core的探索 (5) webmachine
2012-08-07 17:49 0人人IT网不要抄我的烂博客了,私人备忘用的。
相关推荐
动态链接库(so库)是Linux系统下的一种动态链接共享库格式,常用于Linux系统中应用程序与共享库的链接。打包so库通常意味着对多个目标文件(.o文件)或已有库文件进行组合,生成单个的共享库文件(.so文件),以供...
2. **依赖库**: 需要安装必要的库,例如Xcode(对于Mac OS X),以及FFmpeg等多媒体处理工具。 **步骤1 - 获取源码** 从Apple的官方GitHub仓库(或其他来源)下载DSS的源代码。 **步骤2 - 编译与安装** 1. 解压...
GCC(GNU Compiler Collection)和glibc(GNU C Library)是Linux和类Unix系统中广泛使用的工具,它们提供了丰富的功能来帮助开发者优化程序。这篇文章主要探讨了使用GCC编译器和glibc库进行程序优化的几种策略。 1...
- **路径绘制**:介绍如何绘制复杂的线条和路径。 - **图片显示**:教授如何加载和显示图片。 - **坐标系统**:讲解Qt中的坐标系统及其工作原理。 - **涂鸦板**:通过制作一个简单的涂鸦板程序,介绍如何综合运用...
- **使用许可**:允许自由转载,但需保留版权声明,并禁止用于商业用途。 #### 四、核心知识点详解 ##### 1. Qt Creator 安装与配置 - **安装步骤**:详细介绍了Qt Creator的下载、安装流程,以及环境变量设置方法...
请注意,该书上所有的例子都得到了作者的授权,因此请不要进行未经授权的复制或转载。 **设定环境** - **Linux/FreeBSD**: 安装 GNUStep。为了编译GNUstep应用程序,需要执行位于 `/usr/GNUstep/System/Makefiles/...
但Qt Creator 默认是用动态链接的, 就是可执行程序在运行时需要相应的.dll 文件。我们点击生成的.exe 文件,首 先可能显示“没有找到mingwm10.dll,因此这个应用程序未能启动。重新安装 应用程序可能会修复此问题。...