Chinaunix首页 | 论坛 | 博客
  • 博客访问: 73662
  • 博文数量: 30
  • 博客积分: 2142
  • 博客等级: 大尉
  • 技术积分: 351
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-31 10:24
文章分类

全部博文(30)

文章存档

2011年(12)

2010年(14)

2009年(2)

2008年(2)

我的朋友

分类: LINUX

2011-03-24 15:08:07

以前一直不理解连接参数-soname的用处。最近在项目实施过程中遇到共享库连接和运行的一些问题,终于才明白了设置这个参数的用意。

 

下面举例说明:

gcc –O2 -o foo -Wl,-rpath=. main.c libs1.so ../x1/libs2.so

 

查看一下foo中的符号信息

$readelf -a foo | grep Shared

 0x00000001 (NEEDED)                     Shared library: [libs1.so]

 0x00000001 (NEEDED)                     Shared library: [../x1/libs2.so]

 0x00000001 (NEEDED)                     Shared library: [libc.so.6]

 

dynamic linker在初始化foo的时候,会认为libs2.so的位置为../x1,如果libs2.so不在这个位置,那么foo是无法正常运行的,因为dynamic linker会认为libs2.so找不到。

$./foo

./foo: error while loading shared libraries: ../x1/libs2.so: cannot open shared object file: No such file or directory

 

这样就会带来麻烦,假设连接应用程序的时候某个shared library不在当前目录下,并且文件名不符合libXXX.so的形式,那么连接参数就只能使用 ../dir1/myshlib.so 这样的形式,无法变成等价的参数形式:-L../dir1 -lXXX。这样运行的是就要求myshlib.so必须放在相对路径../dir1中。如果myshlib.so以绝对路径/A/B/C/myshlib.so的形式表示,那么运行时就要求myshlib.so也放在目录/A/B/C中。

 

为了解决这个问题,ELF引入了DT_SONAME。在生成shared library的时候指定参数-soname=NAME。这样,用shared library去连接应用程序的时候,即使shared library是以什么形式给出(相对路径或者绝对路径),连接器都以NAME作为该shared library的名字。

 

gcc -shared -Wl,-soname=libs1.so.1 -o libs1.so s1.c && ln -sf libs1.so libs1.so.1

gcc -shared -Wl,-soname=libs2.so.1 -o libs2.so s2.c && ln -sf libs2.so libs2.so.1

gcc -O2 -o foo -Wl,-rpath=. main.c libs1.so ../x1/libs2.so

$readelf -a foo | grep Shared

 0x00000001 (NEEDED)                     Shared library: [libs1.so.1]

 0x00000001 (NEEDED)                     Shared library: [libs2.so.1]

 0x00000001 (NEEDED)                     Shared library: [libc.so.6]

稍微解释一下过程:连接器在连接时发现../x1/libs2.so存在一个DT_SONAME的符号,它的值为libs2.so.1,因此,连接器取libs2.so.1作为shared library的名字,替代掉../x1.libs2.so。但是-soname=libs2.so.1并不会自动生成文件libs2.so.1,因此我们需要手动生成一个符号链接lib2.so.1,使之指向libs2.so,这样运行的时候就不会产生“找不到文件”的错误。

 

总结一下,在linux下使用shared library需要注意一下几个问题:

1.       生成shared library的时候使用-soname参数

2.       生成符号链接文件

3.       shared library放入到LD_LIBRARY_PATH指定的目录中

阅读(2607) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~