现在的程序开发中,基本上我们都会依赖一些系统的或者第三方的动态库。如果我们将我们的可执行程序拷贝到一台新的服务器上,如果新的服务器上没有对应的动态库,那显然我们的可执行程序是无法运行的。这一点是显而易见的。
复杂的情况是新的服务器上有这些动态库,但是动态库的版本不一样,我们的程序是否还可以运行呢?可能大部分人的答案是不行。那正确答案应该是什么呢?
首先说明一下动态库的命名,一般情况下动态的命名采用libxxx.so.a.b.c,其中a代表大版本号,b代表小版本号,c代表更小的版本号。大部分的说法是只要大版本号一致就可以正常运行,否则会提示缺少动态库。一直以来我也坚信这一点,直到最近我提供了一个动态库给别人,我的动态库依赖libboost_filesystem.so.1.58.0,别人的设备上只有libboost_filesystem.so.1.63.0,按照之前的认知别人应该是可以直接调用的,但是问题来了,程序跑不起来,提示缺少so。
要了解这个问题为什么发生,必须要介绍一个名词:soname。一般情况下libxxx.so.a.b.c的soname是libxxx.so.a,所以如果只是小版本变化,so的soname并没有发生变化,而进程依赖so是根据soname查找的,所以一般情况下我们说只要大版本号一致就可以正常运行。但是并不是所以的so的soname都是按照libxxx.so.a的格式定义的,比如我遇到的libboost_filesystem.so.1.58.0,它的soname和它本身的名字一样,也是libboost_filesystem.so.1.58.0,所以尽管主版本号一致,但是程序还是无法运行。
那么一个给定的so我们怎么知道它的soname呢?使用命令readelf -d libxxx.so.a.b.c即可以查看:
总结一下就是如果两个so的soname是一样的,那么它们就可以互相替换而不影响程序运行,否则不可互相替换。