打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux C编程(8) 使用相对路径加载动态库

商业程序如何加载自己的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 qtcreatorDynamic 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]。
现在的问题是,可执行文件如何知道自身所在目录。
ORIGINORIGIN更详细的信息,可参考此文档

例子
例子目录结构如下
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 -lfoolib/libfoo.so:lib/foo.c    gcc -g -Wall -fPIC -shared -o lib/libfoo.so lib/foo.c

foo.c文件源码

#include <stdio.h>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拷贝到其他目录试试。发现程序也可以正常运行。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
银河麒麟系统QtCreator不能切换中文输入法问题解决
【转】gcc指定头文件路径及动态链接库路径
warning: needed by not found (try using -rpath or -rpath-link)
g 编译动态链接库和静态链接库
linux使用gcc编译c语言共享库步骤
Linux 动态库相关知识整理
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服