>gcc -g -c -fPIC -Wall sources
>gcc -g -shared -o xxx.so objects
>gcc -g -fPIC -Wall sources -shared -o xxx.so
>nm object | grep _GLOBAL_OFFSET_TABLE_ #位置独立的代码,确定一个目标在编译的时候是否使用了-fPIC选项,_GLOBAL_OFFSET_TABLE_.
>readelf -s object|grep _GLOBAL_OFFSET_TABLE_
>objdump --all-headers xxx.so|grep TEXTREL #如果产生了输出,那么指定的共享库中至少存在一个目标模块在编译时没有指定-fPIC选项.
>readelf -d xxx.so|grep TEXTREL
>gcc -g -Wall -o prog sources xxx.so #prog 的运行需要指定 LD_LIBRARY_PATH 环境变量.
>gcc -g -c -fPIC -Wall sources #共享库的soname,Wl,-soname选项是传给连接器的指令以将共享库libxxx.so的soname设置为libbar.so.
>gcc -g -shared -Wl,-soname,libbar.so -o libxxx.so objects
>objdump -p libxxx.so|grep SONAME #确定共享库的是否包含soname.
>readelf -d libxxx.so|grep SONAME
>gcc -g -Wall -o prog sources libxxx.so #LD_LIBRARY_PATH=. ./prog : prog,error in loading shared libraries:libbar.so:cannot open shared object file:no such file or directory.
>ln -s libxxx.so libbar.so #解决办法,LD_LIBRARY_PATH=. ./prog 没出现上面的错误了.
>ldd prog #共享库的有用工具,ldd,objdump,readelf .
>nm -A /usr/lib/lib*.so 2>/dev/null|grep 'crypt$' #查找那个库定义了crypt()函数.
名称 格式 描述
------------------------------------------------------
真实名称 libname.so.maj.min 保存库代码的文件,每个库的major-plus-minor版本都存在一个真实名称.
soname libname.so.maj 库的每个主要版本都存在一个soname;在链接时被嵌入到可执行文件中,在运行时用来找出指向相应的(最新的)真实名称的同名符号链接所引用的库.
链接器名称 libname.so 指向真实名称或最新的,soname的符号链接,只存在一个实例;允许构建版本独立的链接命令.
--------------------- -------------------- ----------------------
真实名称 soname 链接器的名称
libname.so.maj.min libname.so.maj libname.so
------------ -------> ------------- -----------> -----------------
(常规文件) (符号链接) (符号链接)
库模块的目标代码 libname.so.maj.min libname.so.maj
-------------------- --------------------- -----------------------
>gcc -g -c -fPIC -Wall sources #使用标准规范创建共享库
>gcc -g -shared -Wl,-soname,libxxx.so.1 -o libxxx.so.1.0.1 objects #创建共享库,真实名称为 libxxx.so.1.0.1,soname 为 libxxx.so.1.
>ln -sv libxxx.so.1.0.1 libxxx.so.1 #为soname和链接器名称创建恰当的符号链接.
>ln -sv libxxx.so.1 libxxx.so
>ls -l libxxx.so*|awk '{print $1,$9,$10,$11}' #使用ls验证配置.
>gcc -g -Wall -o prog sources -L. -lxxx $LD_LIBRARY_PATH=. ./prog
>mv libxxx.so.1.0.1 /usr/lib #安装共享库,/usr/lib,/usr/local/lib;ld.so.conf or /etc/ld.so.cache. ldconfig(8):ldconfig -p 会显示/etc/ld.so.cache的当前内容,-N 防止缓存重建 -X 阻止soname符号链接的创建 -v 输出描述其执行的动作信息.
>cd /usr/lib && ln -sv libxxx.so.1.0.1 libxxx.so.1 && ln -sv libxxx.so.1 libdemo.so
>mv libxxx.so.1.0.1 libxxx.so.2.0.0 /usr/lib #安装一个库的两个不同的主要版本.
>ldconfig -v|grep libxxx
>cd /usr/lib && ls -l libxxx*|awk '{print $1,$9,$10,$11}'
ln -s libxxx.so.2 libxxx.so #为链接器创建符号链接.
>mv libxxx.so.2.0.1 /usr/lib #更新一个库的2.x次要版本.
>ldconfig -v|grep -i libxxx
>gcc -g -c -fPIC -Wall sources
>gcc -g -shared -Wl,-soname,libxxx.so.1 -o libxxx.so.1.0.1 objects
>/sbin/ldconfig -nv .
>ls -l libxxx.so*|awk '{print $1,$9,$10,$11}'
>gcc -g -c -fPIC -Wall sources #升级共享库
>gcc -g -shared -Wl,-soname,libxxx.so.1 -o libxxx.so.1.0.2 objects
>mv libxxx.so.1.0.2 /usr/lib
>ldconfig -v|grep libxxx
>gcc -g -c -fPIC -Wall sources
>gcc -g -shared -Wl,-soname,libxxx.so.2 -o libxxx.so.2.0.0 objects
>mv libxxx.so.2.0.0 /usr/lib
>ldconfig -v|grep -i libxxx
>cd /usr/lib
>ln -sf libxxx.so.2 libxxx.so
##########两种通知动态链接器共享库的位置的方法,使用LD_LIBRARY_PATH 环境变量和将共享库安装到其中一个标准库目录中(/lib,/usr/lib,/usr/local/lib 或在/etc/ld.so.conf中列出其中一个目录).##########
>gcc -g -Wall,-rpath,/path -o prog sources libxxx.so #在目标文件中指定搜索目录,将字符串/path复制到了可执行文件prog的运行是库路径(rpath)列表中;因此当运行这个程序时,动态链接器在解析共享库引用时还会搜索这个目录.-rpath 选项可以多次指定,在一个rpath选中可以指定由多个分号分割开来的目录列表.
##########-rpath选项的替代方案是LD_RUN_PATH环境变量.可以将多个分号分隔开的目录的字符串赋给该变量,当构建可执行文件时可以将这个变量作为rpath列表来使用.只有当构建可执行文件时不知定-rpath选项时才会使用LD_RUN_PATH变量.##########
prog d1/libx1.so d2/libx2.so
(prog.c) (modx1.c) (modx2.c)
main(){x1();} x1(){x2();} x2(){}
>cd /path/d2 #首先在/path/d2目录中构建libx2.so(这里省略了库的版本号和soname).
>gcc -g -c -fPIC -Wall modx2.c
>gcc -g -shared -o libx2.so modx2.o
>cd /path/d1 #接着在/path/d1目录中构建libx1.so;由于libx1.so依赖于libx2.so,并且libx2.so位于一个非标准目录中,因此指定libx2.so的运行时位置时需要使用-rpath链接器选项.这个选项的取值与库的链接时位置(-L选项指定)可以不同,尽管在这个例子中这个两个位置是相同的.
>gcc -g -c -Wall -fPIC modx1.c
>gcc -g -shared -o libx1.so modx1.o -Wl,-rpath,/path/d2 -L/path/d2 -lx2
>cd /path/ #最后在/path目录中构建主程序,由于主程序使用了libx1.so并且这个库位于一个非标准目录中,因此还需要使用-rpath链接器选项;注意在链接主程序时无需指定libx2.so,由于链接器能够分析libx1.so中的rpath列表,因此它能够够找到libx2.so同时在静态库链接阶段解析出所有的符号.
>gcc -g -Wall -o prog sources -Wl,-rpath,/path/d1 -L/path/d1 -lx1
>objdump -p prog|grep PATH #检查prog和libx1.so,以便查看他们的rpath列表内容.
>objdump -p d1/libx1.so|grep PATH #通过查找readelf --dynamic or readelf -d 查看rpath列表.
>ldd prog #查看prog的完整的动态依赖列表.
###########ELF DT_RPATH,DT_RUNPATH条目###########
在第一版ELF规范中,只有一种rpath列表能够被嵌入到可执行文件或共享库中,它对应于ELF文件中的DT_RPATH标签;后续的ELF规范舍弃了DT_RPATH,同时引入了一种新标签DT_RUNPATH来表示rpath列表.这两种rpath列表之间的差别在于当动态链接器在运行时搜索共享库时他们相对于LD_LIBRARY_PATH环境变量的优先级:DT_RPATH的优先级更高,而DT_RUNPATH的优先级则更低.
在默认情况下,链接器会将rpath列表创建为DT_RPATH标签;为了让链接器将rpath列表创建为DT_RUNPATH条目必须要额外使用--enable-new-dtags(启用新动态标签)链接器选项.
>gcc -g -Wall -o prog sourc
share.txt-共享库
最新推荐文章于 2021-06-05 13:47:37 发布
本文详细探讨了共享库的概念,包括其在软件开发中的作用,如何创建和使用共享库,以及在不同操作系统上的实现方式。同时,文章还讨论了共享库与静态库的区别,并举例说明了在实际项目中如何优化资源利用和提高程序效率。
摘要由CSDN通过智能技术生成