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

  • Linux 中动态链接库的版本号以及ldconfig已关闭评论
  • 5 views
  • A+
所属分类:linux

动态链接库的三个名字

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的依赖

 
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

  • 我的微信
  • 微信扫一扫
  • weinxin
  • 微信公众号
  • 微信公众号扫一扫
  • weinxin
avatar