商业程序如何加载自己的so

使用LD_LIBRARY_PATH的缺点是要实现设置LD_LIBRARY_PATH。不够自动化。那么大型的商业程序是如何加载自己的so呢。

这里以QtCreator为例。

QtCreator安装在/home/xxx/Qt5.3.1目录下。使用ldd查看qtcreator依赖的so。结果如下:

xxx@ubuntu:~/Qt5.3.1/Tools/QtCreator/bin$ ldd qtcreator

linux-gate.so.1 => (0xb7701000)

libExtensionSystem.so.1 => /home/xxx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/libExtensionSystem.so.1 (0xb76c2000)

libQt5Widgets.so.5 => /home/xxx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/libQt5Widgets.so.5 (0xb707e000)

libQt5Network.so.5 => /home/xxx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/libQt5Network.so.5 (0xb6f19000)

libQt5Gui.so.5 => /home/xxx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/libQt5Gui.so.5 (0xb69d8000)

libQt5Core.so.5 => /home/xxx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/libQt5Core.so.5 (0xb649d000)

libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb646b000)

libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb6382000)

libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb6364000)

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb61b6000)

libgobject-2.0.so.0 => /usr/lib/i386-linux-gnu/libgobject-2.0.so.0 (0xb6164000)

libglib-2.0.so.0 => /lib/i386-linux-gnu/libglib-2.0.so.0 (0xb6058000)

libX11.so.6 => /usr/lib/i386-linux-gnu/libX11.so.6 (0xb5f24000)

libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb5edd000)

libGL.so.1 => /usr/lib/i386-linux-gnu/mesa/libGL.so.1 (0xb5e7d000)

libicui18n.so.52 => /home/xx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/./libicui18n.so.52 (0xb5c53000)

libicuuc.so.52 => /home/xxx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/./libicuuc.so.52 (0xb5ad7000)

libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb5ad2000)

libgthread-2.0.so.0 => /usr/lib/i386-linux-gnu/libgthread-2.0.so.0 (0xb5ace000)

librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0xb5ac5000)

/lib/ld-linux.so.2 (0xb7702000)

libffi.so.6 => /usr/lib/i386-linux-gnu/libffi.so.6 (0xb5abe000)

libpcre.so.3 => /lib/i386-linux-gnu/libpcre.so.3 (0xb5a80000)

libxcb.so.1 => /usr/lib/i386-linux-gnu/libxcb.so.1 (0xb5a5e000)

libglapi.so.0 => /usr/lib/i386-linux-gnu/libglapi.so.0 (0xb5a45000)

libXext.so.6 => /usr/lib/i386-linux-gnu/libXext.so.6 (0xb5a32000)

libXdamage.so.1 => /usr/lib/i386-linux-gnu/libXdamage.so.1 (0xb5a2e000)

libXfixes.so.3 => /usr/lib/i386-linux-gnu/libXfixes.so.3 (0xb5a28000)

libX11-xcb.so.1 => /usr/lib/i386-linux-gnu/libX11-xcb.so.1 (0xb5a25000)

libxcb-glx.so.0 => /usr/lib/i386-linux-gnu/libxcb-glx.so.0 (0xb5a0c000)

libxcb-dri2.so.0 => /usr/lib/i386-linux-gnu/libxcb-dri2.so.0 (0xb5a06000)

libxcb-dri3.so.0 => /usr/lib/i386-linux-gnu/libxcb-dri3.so.0 (0xb5a02000)

libxcb-present.so.0 => /usr/lib/i386-linux-gnu/libxcb-present.so.0 (0xb59fe000)

libxcb-sync.so.1 => /usr/lib/i386-linux-gnu/libxcb-sync.so.1 (0xb59f7000)

libxshmfence.so.1 => /usr/lib/i386-linux-gnu/libxshmfence.so.1 (0xb59f3000)

libXxf86vm.so.1 => /usr/lib/i386-linux-gnu/libXxf86vm.so.1 (0xb59ed000)

libdrm.so.2 => /usr/lib/i386-linux-gnu/libdrm.so.2 (0xb59df000)

libicudata.so.52 => /home/xxx/Qt5.3.1/Tools/QtCreator/bin/./../lib/qtcreator/././libicudata.so.52 (0xb4373000)

libXau.so.6 => /usr/lib/i386-linux-gnu/libXau.so.6 (0xb436e000)

libXdmcp.so.6 => /usr/lib/i386-linux-gnu/libXdmcp.so.6 (0xb4367000)

在看一下本身直接加载的动态库:

xxx@ubuntu:~/Qt5.3.1/Tools/QtCreator/bin$ readelf --dynamic qtcreator

Dynamic section at offset 0x11eb0 contains 30 entries:

标记 类型 名称/值

0x00000001 (NEEDED) 共享库:[libExtensionSystem.so.1]

0x00000001 (NEEDED) 共享库:[libQt5Widgets.so.5]

0x00000001 (NEEDED) 共享库:[libQt5Network.so.5]

0x00000001 (NEEDED) 共享库:[libQt5Gui.so.5]

0x00000001 (NEEDED) 共享库:[libQt5Core.so.5]

0x00000001 (NEEDED) 共享库:[libpthread.so.0]

0x00000001 (NEEDED) 共享库:[libstdc++.so.6]

0x00000001 (NEEDED) 共享库:[libgcc_s.so.1]

0x00000001 (NEEDED) 共享库:[libc.so.6]

0x0000000f (RPATH) Library rpath: [$ORIGIN/../lib/qtcreator]

秘密就在这句:0x0000000f (RPATH) Library rpath: [$ORIGIN/../lib/qtcreator]

rpath与ORIGIN

rpath是gcc的一个参数。rpath添加一个目录。当程序被加载时,搜寻此目录,寻找动态库。rpath添加的目录信息保存在可执行文件中。即使这句

0x0000000f (RPATH) Library rpath: [xxx]。

现在的问题是,可执行文件如何知道自身所在目录。

ORIGIN变量代表了此目录。关于ORIGIN更详细的信息,可参考此文档。

例子

例子目录结构如下

src

…main.c

…Makefile

…lib/foo.c

操作系统:ubuntu 14 32位

编译i:gcc 4.8

main.c文件源码

void test_tk();

int main(void)

{

test_tk();

return 0;

}

Makefile文件内容

main:main.c lib/libfoo.so

gcc -L${shell pwd}/lib -g -Wall -o test -Wl,-rpath,'$$ORIGIN/lib' main.c -lfoo

lib/libfoo.so:lib/foo.c

gcc -g -Wall -fPIC -shared -o lib/libfoo.so lib/foo.c

foo.c文件源码

#include

void test_tk()

{

printf("called!\n");

}

编译,生成test可执行文件。

执行readelf –dynamic test 来看加载的动态库。

Dynamic section at offset 0xf04 contains 26 entries:

标记 类型 名称/值

0x00000001 (NEEDED) 共享库:[libfoo.so]

0x00000001 (NEEDED) 共享库:[libc.so.6]

0x0000000f (RPATH) Library rpath: [$ORIGIN/lib]

..........................................................

运行test。执行结果位

called!

可以讲src拷贝到其他目录试试。发现程序也可以正常运行。

Linux添加相对库路径,Linux C编程(8) 使用相对路径加载动态库-rpath和$ORIGIN相关推荐

  1. Linux系统程序运行时加载动态库路径顺序

    程序运行时加载动态库路径顺序(Linux) 在linux系统中,如果程序需要加载动态库,它会按照一定的顺序(优先级)去查找: 链接时路径(Link-time path)和运行时路径(Run-time ...

  2. linux直接运行程序加载动态库失败,扣丁学堂Linux培训详解程序运行时加载动态库失败解决方法...

    今天扣丁学堂Linux培训老师给大家介绍一下关于Linux程序运行时加载动态库失败的解决方法,希望对同学们学习有所帮助,下面我们一起来看一下吧. Linux下不能加载动态库问题 当出现下边异常情况 . ...

  3. linux加载动态库问题

    当我们在linux系统引用动态库时,经常会遇到一个问题,加入我们需要的动态库没有在系统的默认目录下,我们编译时使用-L指定了动态库的路径,编译时没有问题,但是执行调用该动态库的可执行文件时,却提示找不 ...

  4. linux平台 加载动态库dlsym返回null

    linux 平台加载动态库通常使用dlopen,dlsym,dlclose三个函数实现 最近写了一个小程序,遇到dlsym总是调用失败返回空值,查找了很多相关的资料,确定动态库的创建有问题.下面是最初 ...

  5. sunPKCS11加载动态库(转)

    sunPKCS11加载动态库(转) http://www.cnblogs.com/sunfb/archive/2013/03/01/2938491.html 这篇文章不介绍具体的编程方法,而是针对PK ...

  6. tableview动态修改和删除_Ubuntu加载动态库失败的解决方案

    在ubuntu下代码编译通过的情况下,经常出现运行时加载动态库出错的情况.这些问题很琐碎,不具备任何技术含量,纯属耽误时间,这也是linux系统的通病,花里胡哨,故弄玄虚. 为了减少初学者在这种无意义 ...

  7. php无法加载dll插件,php无法加载动态库怎么办

    php无法加载动态库的解决办法:1.将PHP的集成包里的"libmySQL.dll"复制到system32目录下:2.将PHP的解压目录添加到PATH里:3.在Apache的配置文 ...

  8. 使用Poco实现插件方式加载动态库

    动态库封装虚基类 //AbstractPlugin.h #ifndef __ABSTRACTPLUGIN_H__ #define __ABSTRACTPLUGIN_H__#include <st ...

  9. 加载动态库失败(loadLibrary返回为空)的几种解决办法

    如果遇到了以下几种问题,也许可以在本文找到解决方法: 一.版本更新后,原本正常的功能突然无法使用了: 二.VS编译的时候,弹出"xxx(win32):已加载"xx.dll" ...

  10. LoadLibrary加载动态库失败

    [1]LoadLibrary加载动态库失败的可能原因以及解决方案: (1)dll动态库文件路径不对.此场景细分为以下几种情况: 1.1 文件路径的确错误.比如:本来欲加载的是A文件夹下的动态库a.dl ...

最新文章

  1. 快速理解VirtualBox的四种网络连接方式
  2. .NET3.0已经Pre-release了
  3. python软件是哪个国家的品牌_有哪些好用的软件被国人误认为是外国研发的?
  4. IntelliJ IDEA + Maven环境编写第一个hadoop程序
  5. go设置后端启动_开源一个go的H5游戏服务端开发框架
  6. LeetCode OJ - Longest Substring Without Repeating Characters
  7. 金鹏GB28181平台对接
  8. Element UI踩坑记 —— el-table中 formatter 的属性居然失效了
  9. linux删除用户名命令,linux删除用户命令
  10. miui8 android.policy,小米MIUI8系统调教记:轻快好省 畅爽静稳
  11. MKS_SGEN_L V1.0 marlin 固件编译
  12. DZS-115/DC110V中间继电器
  13. xml解析之dom、dom4j、SAX
  14. 营养学和计算机交叉,营养配餐系统综述
  15. 网关系统就该这么设计,万能通用,稳的一批!
  16. Linux下实现苹果AirPlay音频服务器
  17. Stereogram(极射赤面)投影--主要用于中高纬和极区的天气图
  18. 【时空序列】AAAI2021| 利用时空融合图神经网络进行交通流量预测
  19. 在打破传统保险业的“玻璃屋顶” 之前,AI+保险还需跨过几道坎
  20. 蓝桥杯 — IAP15F2K61S2-89C52 转换板说明文件

热门文章

  1. linux 查看新增文件夹记录_微信7.0.23测试版,新增查看访客记录,朋友圈内容能折叠?...
  2. DQL——数据查询语言
  3. linux源代码剖析之二boot
  4. Linux命令解释之groupadd,groupdel,groupmod,groupmems
  5. ip8plus多重_【苹果 iPhone 8 Plus 手机使用总结】容量|处理器|手感_摘要频道_什么值得买...
  6. redmin3 忘记管理密码找回方法
  7. tipask mysql调取dedecms_如何实现dedecms外部数据库调用
  8. 发的楷体怎么写_孩子作业实在写不完,父母该怎么办?我直接给老师发信息
  9. 安装ISE.14.7后仿真时遇到的问题与解决
  10. 微信快速开发框架(五)-- 利用快速开发框架,快速搭建微信浏览博客园首页文章...