顶嵌|嵌入式培训|嵌入式Linux培训|承接嵌入式项目开发 2009-02-26 10:01:16 作者:顶嵌开源 来源:原创 文字大小:[大][中][小] |
对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“
error while loading shared libraries
”这样的错误,这是典型的因为需要的动态库不在动态链接器
ld.so
的搜索路径设置当中导致的
。
具体说来,动态链接器
ld.so
按照下面的顺序来搜索需要的动态共享库:
1
.
ELF
可执行文件中动态段中
DT_RPATH
所指定的路径。这实际上是通过一种不算很常用,却比较实用的方法所设置的:编译目标代码时,可以对
gcc
加入链接参数“
-Wl,-rpath
”指定动态库搜索路径;
2
.环境变量
LD_LIBRARY_PATH
指定的动态库搜索路径;
3
.
/etc/ld.so.cache
中所缓存的动态库路径(如果支持
ld.so.cache
的话)。这可以通过修改配置文件
/etc/ld.so.conf
中指定的动态库搜索路径来改变;
4
.默认的动态库搜索路径
/lib
;
5
.默认的动态库搜索路径
/usr/lib
。
在嵌入式Linux系统的实际应用中,1和2被经常使用,也有一些相对简单的的嵌入式系统会采用4或5的路径来规范动态库。3在嵌入式系统中使用的比较少,因为有很多系统根本就不支持ld.so.cache。
4和5的方式非常简单,只要将所需要的库放到/lib或/usr/lib就可以解决找不到库的问题,不过对于大一些的系统来说,不太方便管理。1和2的方式要稍微复杂一些,下面我们用一个非常简单的例子来说明如何应用。
首先编写一个最简单的动态共享库,源代码
pirnt.c
如下:
注意将它编译成共享库:
调用该共享库main.c
代码如下:
编译之后的运行结果如下:
这便是典型的找不到动态库的错误。通常我们可以通过设置环境变量
LD_LIBRARY_PATH
来指定动态库的搜索路径(即上面的方法2),比如这样就可以正确运行了:
但这种方法有一个明显的缺点:一旦
LD_LIBRARY_PATH
被设定,则在这个环境变量生效的范围之内,所有其他的
ELF
可执行程序也会按照这个顺序去搜索动态库,这样势必会造成搜索时的一些浪费。
我们也可以使用另外一种方案来解决这种问题,即利用参数“
-Wl,-rpath
”在编译时指定运行时的搜索路径(即上面的方法1),如下所示:
我们首先
unset
了
LD_LIBRARY_PATH
,可以看到它已经不再有效了(当然这不是使用参数“
-Wl,-rpath
”的必要步骤,在这里只是为了说明它已经不再起作用了),而且
”pfoo”
程序运行时也会发生找不到库的错误,而我们加入编译参数“
-Wl,-rpath,./
”之后得到的
pfoo_r
程序则能正常运行。
事实上我们可以通过
readelf
工具来查看两个文件的差异:
“
readelf -d
”可以用来查看
ELF
文件的动态节
(Dynamic Section)
。对比
pfoo
和
pfoo_r
的结果我们可以发现,
pfoo_r
中多出来了
RPATH
项,指定
”Library rpath: [./]”
。通过这种方式,我们可以用非常小的代价(仅增加几乎可以忽略的空间开销),对每个
ELF
文件都指定最优化的搜索路径,达到提升性能的目的。这是我们比较推荐的一种方法。当然了,具体如果操作依赖于具体的软件系统的情况,简单的系统中直接将所有的库都放到
/lib
下也未尝不是一种简单易行的优化方案。
|