• 6485阅读
  • 9回复

Qt load .so文件的问题 [复制链接]

上一主题 下一主题
离线danny1987
 
只看楼主 倒序阅读 楼主  发表于: 2010-12-20
现在遇到的问题就是Qt 在load需要的.so文件时查找的顺序问题。debug信息如下:
1291420811.586906 open("/usr/lib/tls/libXfixes.so.3", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000236>
1291420811.587647 open("/usr/lib/sse2/libXfixes.so.3", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000235>
1291420811.588445 open("/usr/lib/libXfixes.so.3", O_RDONLY) = 5 <0.000297>

问题就是说它默认的会去查找usr/lib/tls/libXfixes 等目录,但是这些目录里是都没有那些.so文件的。一般都是在默认的usr/lib目录下
直接能找到.现在就是每个load这些库都会先查找这几个无关的目录,然后再在usr/lib下找,这样就浪费了时间。
而且这个问题在handset上特别的严重,但是在netbook和pc上这个问题就基本没有这个问题。不知道是不是什么配置的问题呢?
坐等高人解答
离线danny1987
只看该作者 1楼 发表于: 2010-12-20
或者说换个问题
Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后,一般都复制到这两个目录中。其他的什么环境变量,ld.so.conf我都没改,
所以当程序需要这些库的时候就会自动到上面那2个目录去查找。现在就是在handset设备上,默认的会先去查找上面2个目录的子目录,
在搜索这个目录本身的文件。不知道有没有什么方法可以改变这个配置
离线cycloneii

只看该作者 2楼 发表于: 2010-12-20
这和库文件的搜索路径有关系
1)程序里面使用了dlopen之类的函数,那么没有办法,即使不存在这个库,也必须先查找并试图打开这个库
2)如果你编译的时候链接器指定了rpath参数,那么这个库的路径会编译进elf可执行文件,运行时默认会优先使用rpath里面指定的库路径
3)如果你使用了LD_LIBRARY_PATh或者LD_PRELOAD,那么也会优先搜索这两个环境变量使用的路径
4)接下来才是/etc/ld.so.preload和/etc/ld.so.conf
比如在我的linux系统上qt4程序就不会去打开/usr/lib/tls/libXfixes.so.3,所以我估计很有可能是你编译的问题
离线danny1987
只看该作者 3楼 发表于: 2010-12-20
回 2楼(cycloneii) 的帖子
我查了下,好像并没有用到dlopen函数,而且LD_LIBRARY_PATH和LD_PRELOAD也是没有设置的。
离线cycloneii

只看该作者 4楼 发表于: 2010-12-20
Re:回 2楼(cycloneii) 的帖子
引用第3楼danny1987于2010-12-20 16:06发表的 回 2楼(cycloneii) 的帖子 :
我查了下,好像并没有用到dlopen函数,而且LD_LIBRARY_PATH和LD_PRELOAD也是没有设置的。

你用readelf来看看这些库Dynamic section的属性,看看其中是否有Library rpath字段
离线danny1987
只看该作者 5楼 发表于: 2010-12-20
回 4楼(cycloneii) 的帖子
用readelf -?呢
离线cycloneii

只看该作者 6楼 发表于: 2010-12-20
给你看一个例子
gcc -Wl,-rpath,/home/arc/test,-rpath,/lib/,-rpath,/usr/lib/,-rpath,/usr/local/lib 1.c
readelf -d a.out
Dynamic section at offset 0xf10 contains 23 entries:
  Tag        Type                         Name/Value
0x00000001 (NEEDED)                     Shared library: [libc.so.6]
0x0000000f (RPATH)                      Library rpath: [/home/arc/test:/lib/:/usr/lib/:/usr/local/lib]
0x0000001d (RUNPATH)                    Library runpath: [/home/arc/test:/lib/:/usr/lib/:/usr/local/lib]
0x0000000c (INIT)                       0x8048320
0x0000000d (FINI)                       0x804850c
0x00000004 (HASH)                       0x80481c4
0x6ffffef5 (GNU_HASH)                   0x80481ec
0x00000005 (STRTAB)                     0x804825c
0x00000006 (SYMTAB)                     0x804820c
0x0000000a (STRSZ)                      120 (bytes)
0x0000000b (SYMENT)                     16 (bytes)
0x00000015 (DEBUG)                      0x0
0x00000003 (PLTGOT)                     0x8049ff4
0x00000002 (PLTRELSZ)                   24 (bytes)
0x00000014 (PLTREL)                     REL
0x00000017 (JMPREL)                     0x8048308
0x00000011 (REL)                        0x8048300
0x00000012 (RELSZ)                      8 (bytes)
0x00000013 (RELENT)                     8 (bytes)
0x6ffffffe (VERNEED)                    0x80482e0
0x6fffffff (VERNEEDNUM)                 1
0x6ffffff0 (VERSYM)                     0x80482d4
0x00000000 (NULL)                       0x0

离线danny1987
只看该作者 7楼 发表于: 2010-12-21
回 6楼(cycloneii) 的帖子
发现好像不是这个的问题。另外还有如果把LD_LIBRARY_PATH设置成了usr/lib的话,会不会有影响呢?
离线danny1987
只看该作者 8楼 发表于: 2010-12-21
或者我还看到说会与spec文件有影响?
离线cycloneii

只看该作者 9楼 发表于: 2010-12-21
引用第8楼danny1987于2010-12-21 10:18发表的  :
或者我还看到说会与spec文件有影响?

不会跟spec有关,当你编译成二进制之后,是和这些东西无关的。
你不要光用readelf -d 《a.out》,还要看依赖的so文件,也有可能是so文件里面指定了rpath
实在不行你用strace a.out来看看整个系统调用过程过程
LD_LIBRARY_PATH=/usr/lib是不必要的,你可以设置这个环境变量为空再用strace之类的来跟踪系统调用看看
还不行,你看看gcc的手册,查so文件的查找加载过程
快速回复
限100 字节
 
上一个 下一个