linux so 文件的一些问题

对于共享库(so文件),linux编译时和运行时的搜索顺序,可不像windows,他有他自己的规则,需要在开发的时候注意,否则发布之后,就会出现找不到库文件的错误。
在开始讲解这个问题的时候,我们先来看看两个linux命令:

ldd

这个命令,可以查看当前库或应用程序的依赖项

readelf

这个命令,可以读取ELF文件的一些相关信息

以上2个命令,都是查看文件信息非常重要和好用的命令,大家需要掌握。

好了,我们开始讲述本文的正题吧,先假设我们有一个main.c文件,一个libA.c文件,main.c会编译成应用程序main.out,libA.c会编译成共享库libA.so,main.out依赖libA.so。

如果我们在编译时不指定依赖库的搜索路径以及库,而是直接依赖:

gcc -g main.c -o main.out -ldl libA.so
这会怎么样呢?
先用ldd看看
ldd 结果

依赖库似乎被硬编码到了文件中,我们用readelf印证一下看看
readelf结果
那么显然这个应用程序是不能发布给其他人使用的(你总不能让别人创建和你一样的目录吧)

那么如果加上-L -l 指令呢?我们来看看:
gcc -g main.c -o main.out -ldl -L/path/to/your/library/ -lA

还是先用ldd看看
ldd结果
这次没有硬编码的路径了,虽然提示找不到依赖库,但是编译是没问题的。这就是编译时搜索路径和运行时搜索路径的区别。
让我们再用readelf看看
readeld结果
那么这个时候如果发布了程序,程序到哪里找依赖呢?默认就是

/lib
/usr/lib

或者是配置了LD_LIBRARY_PATH环境变量,或者是/etc/ld.so.conf ,总之和windows不一样,不做特殊处理的话,不会在当前目录寻找。
所以如果我们有一些依赖的第三方库要打包一起发布,又不想去动客户机的环境的话,那么就需要指定加载器在你指定的目录加载,比如应用程序当前目录下。

gcc -g main.c -o main.out -ldl -L/path/to/your/library/ -lA -Wl,-rpath='$ORIGIN:$ORIGIN/lib'

这就是rpath的作用,现在咱们再用ldd看看
ldd结果
这里,和第一次硬编码的结果一样,但是是完全不同的两种情况,因为ldd根据rpath找到了依赖库,我们用readelf看看
readeld结果

注意看,多了一个RPATH。

以上是so文件的静态加载方式,除了这种方式以外,还有一种方式,就是动态加载方式,这种方式就是使用dlopen dlsym函数来加载,好处是可以随意指定目录,不好的地方,就是你得额外写一些函数接口声明。

好了,以上就是linux so 文件的一些问题了,希望看完之后,能对你有所帮助。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值