Linux 中动态链接库的版本号以及ldconfig

动态链接库的三个名字

1. realname, 真正的名字,一般情况下如果你有版本,应该在后面加上lib[libraryname].so.[version] eg: libtest.so.1.0.0

2. soname, 在编译动态库的时候指定的名字,这个名字将会被添加到动态库的头部,通过readelf -d 可以查看, 这个名字是可以没有的。一般为lib[libraryname].so.i 或 lib[libraryname].so.i.i.

3. linkname, 可执行文件在加载动态库的时候查找的名字,lib[libraryname].so, 后面没有版本号,若soname存在,最后动态库连接到的是soname,若soname不存在,而linkname直接软连接到真正的库名称上面, 可执行文件就将linkname当作soname.

lrwxrwxrwx 1 root root      28 Aug  1 15:59 /usr/local/lib/libopencv_xfeatures2d.so -> libopencv_xfeatures2d.so.3.4
lrwxrwxrwx 1 root root      30 Aug  1 15:59 /usr/local/lib/libopencv_xfeatures2d.so.3.4 -> libopencv_xfeatures2d.so.3.4.2
-rw-r--r-- 1 root root 3090824 Aug  1 22:07 /usr/local/lib/libopencv_xfeatures2d.so.3.4.2

 

上面的例子就阐述了opencv的连接关系 libopencv_xfeatures2d.so 是linkname, 是编译可执行文件的时候查找的名字,

libopencv_xfeatures2d.so.3.4 是 soname, 这个名字也被嵌入在libopencv_xfeatures2d.so.3.4.2头部,我们通过readelf -d 查看一下

readelf -d /usr/local/lib/libopencv_xfeatures2d.so.3.4.2 | grep soname
 0x000000000000000e (SONAME)             Library soname: [libopencv_xfeatures2d.so.3.4]

这样的做法允许了动态库真正的realname更新的时候(小版本更新,原有接口不变), soname本身的名字不需要改变,linkname一直不需要改变,而linkname软连接的soname对象也不需要改变,只需要改变soname软连接的realname动态库就可以了

1. 可以通过手动改变软连接

2. 可以通过执行ldconfig操作,前提是动态库路径在xx.conf文件中, 或者在LD_LIBRARY_PATH中

若两个realname在头部有同样的soname,ldconfig会选取版本更高的进行软连接。

libtestuser.so  libtestuser.so.1.0  libtestuser.so.1.0.0   

假设现在有这三个文件,分别是我们前面所说的三个linkname, soname, realname,

现在有一个main.cpp, 依赖这个动态库,编译它

注意我已经在/etc/ld.so.conf.d/xx.conf里面添加了这里的路径并且更新了ldconfig,这样linker才能查找到这个库。

g++ main.cpp -o main -L./build -ltestuser

通过两种方式查看一下main的依赖

1.

blindfind@blindfind:~/gitlab/test$ ldd main
	linux-vdso.so.1 =>  (0x00007ffd9c98f000)
	libtestuser.so.1.0 => /home/blindfind/gitlab/test/build/libtestuser.so.1.0 (0x00007f380cd1b000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f380ca0c000)

2.

readelf -d main | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libtestuser.so.1.0]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

可以看见实际上依赖找的是soname,而soname是嵌入在真正的动态库里面的。

再说明一下动态库依赖动态库的问题

如果liba.so 依赖 libb.so, 而main依赖liba.so, 如何做到编译main的时候不指定libb.so的路径?

虽然编译动态库并不需要指定依赖路径,但是这时候指定可以不再main编译的时候再次指定liba依赖的动态库了

blindfind@blindfind:~/gitlab/test$ g++ -shared -fPIC -Wl,-soname,libtestuser.so.1 -o libtestuser.so.1.0.0 testUser.cpp -L. -ltest
blindfind@blindfind:~/gitlab/test$ ls
build  CMakeLists.txt  libtest.so  libtest.so.1  libtest.so.1.0.1  libtestuser.so.1.0.0  main  main.cpp  test.cpp  test.h  testmore  test.o  testUser.cpp  testUser.h
blindfind@blindfind:~/gitlab/test$ ldd libtestuser.so.1.0.0 
	linux-vdso.so.1 =>  (0x00007ffc9d3e2000)
	libtest.so.1 (0x00007ffae2802000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ffae24d5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffae210a000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ffae1e02000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ffae2c08000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ffae1bec000)

 这时候进行指定,可以看见libtestuser依赖了libtest

看一下libtestuser的soname.

readelf -d libtestuser.so.1.0.0  | grep soname
 0x000000000000000e (SONAME)             Library soname: [libtestuser.so.1]

执行ldconfig,可以看见多了libtestuser.so.1 的软连接,这是通过查看libtestuser.so.1.0.0 的soname决定的

blindfind@blindfind:~/gitlab/test$ sudo ldconfig
[sudo] password for blindfind: 
blindfind@blindfind:~/gitlab/test$ ls
build  CMakeLists.txt  libtest.so  libtest.so.1  libtest.so.1.0.1  libtestuser.so.1  libtestuser.so.1.0.0  main  main.cpp  test.cpp  test.h  testmore  test.o  testUser.cpp  testUser.h

然后编译main函数,不指定libtest.so,光指定libtestuser.so, 别忘了先添加linkname的软连接 ln -s libtesetuser.so.1 libtestuser.so

blindfind@blindfind:~/gitlab/test$ g++ main.cpp -o main -L. -ltestuser
blindfind@blindfind:~/gitlab/test$ ldd main
	linux-vdso.so.1 =>  (0x00007ffe03917000)
	libtestuser.so.1 (0x00007f86d92e1000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f86d8fb4000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f86d8be9000)
	libtest.so.1 (0x00007f86d89e7000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f86d86df000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f86d94e5000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f86d84c8000)
blindfind@blindfind:~/gitlab/test$ ./main
4
blindfind@blindfind:~/gitlab/test$ 

main执行成功,而且ldd查看以后,发现libtest.so自动被添加了进来,因为libtestuser.so依赖libtest.so

 

 

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C版本MD5库 参考README.md 内容 #file list makefile #编译文件 md5.c md5.h test_md5_hash.c #测试样例文件 README.md #帮助文件 ========== 该库目前仅仅支持Gun/Linux/Unix 系列的编译 若是winxp/win7/win8 系列请自己包含进去,或者自己重新打包 代码是从bPostgreSQL的库文件copy出来的,经过自己的测试,重新提取打包出来的 目前这个库的代码是在 PG 的 8.5RS 里面用的 MD5 返回的是一个 32位的消息hash因此需要一个char 类型的返回buf query_md5 =(char *)malloc(33); 函数调用 md5_hash(argv[1],query_len,query_md5); argv1 需要加密的数据 argv2 加密数据长度 argv3 密文 MD5.c 里面其他函数不常用,有兴趣的自己看一下吧,注释是用英文写的,基本上都能看 懂,不能看懂的,Google翻译一下就行了 自己的文件编译已测试样例文件为例 make后同时生成静态库和动态库 libminmd5.a 静态库 libminmd5.so 动态库 1、静态库的用法 gcc -o test test_md5_hash.c -L. -lminmd5 -I. -L #库文件的路径, -l #库名字,通常情况下就是 去掉后缀和前缀lib的名字 -I #头文件的路径 PS:动态库和静态库文件同名的建议不要放在一起,不然 ld的时候有可能找错文件 2、动态库的用法 gcc -o test test_md5_hash.c -g -L. -lminmd5 -I. 编译完后,建议将so 文件copy 到/usr/lib 然后执行 ldconfig 或者写死一点 gcc -o test test_md5_hash.c -g -L. -lminmd5 -I. -Wl,-rpath,. -Wl,-rpath,. #告诉ld 从本地找库(W后面是L小写的),rpath里面接的是库文件存在 的路径,正常应用建议用第一种方案,第二种方案在写小测试程序的时候,可以考虑。 至于选静态库还是动态库,就看具体应用场景了,静态库的坏处是把库代码编译进去了, 若是程序按字节收费还是可以的,(PS,吐槽那个写了一个10w,10G的程序国神童)
要下载和编译Linux的libssh2.so版本,可以按照以下步骤进行: 1. 首先,从libssh2官方网站(https://www.libssh2.org/)或者其他可靠的资源库找到最新的libssh2版本的源代码压缩包。 2. 下载源代码压缩包到本地计算机,可以使用命令行工具如wget或者通过浏览器下载。 3. 解压缩源代码压缩包,在命令行使用tar命令进行解压缩。例如,使用以下命令解压缩压缩包: tar -zxvf libssh2-x.x.x.tar.gz (其x.x.x代表源代码压缩包的版本号) 4. 进入解压缩后的libssh2目录,使用cd命令切换到解压后的文件夹内。 5. 使用编译工具(如gcc)对libssh2进行编译,可以使用以下命令进行编译: ./configure make make install 注意:在编译之前,请确保您已经安装了必要的依赖项(如libssl-dev)。 6. 编译完成后,libssh2.so文件将会生成在系统默认的库文件路径,一般为/usr/local/lib。如果您希望将其安装到其他位置,可以在configure命令通过--prefix选项指定安装路径。 7. 可以使用ldconfig命令来刷新系统的动态链接器缓存,以便让系统找到新安装的libssh2.so文件。可以使用以下命令来刷新缓存: sudo ldconfig 8. 现在,您可以在您的应用程序使用libssh2库进行开发和测试。记得在编译应用程序时,使用-L选项指定libssh2.so所在的目录,并使用-lssh2选项链接到libssh2库。 以上是一个简单的示例解释如何在Linux上下载和编译libssh2.so版本。具体步骤和命令可能因系统版本和安装环境而有所不同,建议在实际操作参考官方文档或其他可靠资源。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值