linux dll hell--链接库real name, soname, link name
那么此问题该如何解决的呢?
Linux 系统为解决这个问题,引入了一套机制,如果遵守这个机制来做,就可以避免这个问题。
但是这只事一个约定,不是强制的。
但是建议遵守这个约定,否则同样也会出现 Linux 系统版的 DLL hell 问题。
下面来介绍一个这个机制。
这个机制是通过文件名,来控制共享库(Shared Library)的版本,它有三个名字,分别又有不同的目的。
1)第一个是共享库的实际文件名(Real Name),
它是编译器产生共享库时或人为修改名字后的文件名,该实际文件名就是为了直观地控制共享库版本。
其格式为:lib + math + .so + 主版本号 + 小版本号 + 制作号
如:libmath.so.1.1.1234。
lib 是 Linux 系统上的库的约定前缀名,
math 是库自已的名字,
so 是共享库的后缀名,
1.1.1234 是共享库的版本号,
格式:主版本号 + 小版本号 + 制作(build)号。
主版本号 - 代表当前共享库的版本,
如果共享库提供的接口函数有变化的话,那么这个版本号就要加壹(1);
小版本号 - 如果引入了新的特性(Feature)的话,那么这个版本号就要加壹(1);
制作号 - 一般仅表示修正了Bug。
2)第二个是共享库的简短文件名(soname - Short for shared object name),
它是可执行程序加载它时,要寻找的文件名。
其格式为:lib + math + .so + 主版本号
如:libmath.so.1
注:在编译链接生成一个实际文件名的共享库时,同时也将简短文件名写进了共享库的文件头里面。
可以用此命令来查看:$readelf -d 共享库的实际文件名
3)第三个是共享库的连接文件名(Link Name),
是专门为可执行程序生成阶段链接共享库时用的名字,不带任何版本信息的。
其格式为:lib + math + .so
如:libmath.so。
在可执行程序加载共享库时: 通过共享库的简短文件名在给定的路径下寻找共享库。
#include <stdio.h>
void hello() {
printf("libhello");
}
int main() {
hello();
}
Dynamic section at offset 0xe08 contains 25 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libhello.so.0]
0x000000000000000c (INIT) 0x588
0x000000000000000d (FINI) 0x708
0x0000000000000019 (INIT_ARRAY) 0x200de8
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x200df0
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x1f0
0x0000000000000005 (STRTAB) 0x380
0x0000000000000006 (SYMTAB) 0x230
0x000000000000000a (STRSZ) 190 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x201000
0x0000000000000002 (PLTRELSZ) 72 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x540
0x0000000000000007 (RELA) 0x480
0x0000000000000008 (RELASZ) 192 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x460
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x43e
0x000000006ffffff9 (RELACOUNT) 3
0x0000000000000000 (NULL) 0x0
total 20
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
total 20
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
lrwxrwxrwx. 1 qingze qingze 17 Nov 29 15:30 libhello.so.0 -> libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
total 20
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
lrwxrwxrwx. 1 qingze qingze 13 Nov 29 15:33 libhello.so -> libhello.so.0
lrwxrwxrwx. 1 qingze qingze 17 Nov 29 15:30 libhello.so.0 -> libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
total 32
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
lrwxrwxrwx. 1 qingze qingze 13 Nov 29 15:33 libhello.so -> libhello.so.0
lrwxrwxrwx. 1 qingze qingze 17 Nov 29 15:30 libhello.so.0 -> libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8538 Nov 29 15:36 main
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
gcc编译链接动态库时,很有可能编译通过,但是执行时,找不到动态链接库,那是
因为-L选项指定的路径只在编译时有效,编译出来的可执行文件不知道-L选项后面的值,
当然找不到。可以用ldd <your_execute>看看是不有 ‘not found’在你链接的库后面,
解决方法是通过-Wl,rpath=<your_lib_dir>,使得execute记住链接库的位置
个人理解:
参考了网上一些资料,一步步执行时会发生错误,我按照以上方法成功了,所以我认为当动态链接库版本发生变化时只要重新执行第4步,将libhello.so链接到新版本即可!
有待求证!!!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。