Linux下动态库有三个名字:real name、so name、link name。
- real name:共享库本身的名字,命名格式为libname.so.x.y.z,lib是前缀,name是共享库的名字,so是后缀,x是主版本,y是次版本号,z是发布版本号。
主版本号、次版本号和发布版本号的意义如下:
主版本号:表示库的重大升级,比如改变了原有的接口。不同主版本号的库是不兼容的,要保证向下兼容就不能删除旧版本的动态库。
次版本号:表示库的增量升级,比如增加了新的接口,但原有接口保持不变。高的次版本号的库向下兼容低的次版本号的动态库,原有的版本库是可以不保留的。
发布版本号:表示指示改正了一些错误或者是性能优化等,接口没有增加,也没有改变,因此也是向下兼容的。
- so name:是通过ldconfig命令,来创建的指向真正的动态库(real name)的链接,so name的命名规则是,real name去掉次版本号和发布版本号,格式为libname.so.x。
- link name:是so name的软链接,命名规则是,real name去掉主版本号、次版本号和发布版本号,格式为libname.so,编译时,通过参数-lname来链接。
下面通过实际的例子来说明动态库的编译和链接:
首先,建立hello.c和hello.h两个文件,然后将他们编译成动态链接库。
hello.c文件:
#include <stdio.h>
void hello (void)
{
printf("Hello, library world.\n");
}
hello.h文件:
#ifndef __HELLO_H__
#define __HELLO_H__
void hello (void);
#endif
执行如下命令,编译生成共享库
$gcc hello.c -fPIC -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0
编译完成后,只生成了libhello.so.0.0.0,并未生成libhello.so.0,若要生成libhello.so.0需要做如下操作:
在/etc/ld.so.conf文件中指定库的路径,在文件中添加:libhello.so.0.0.0这个库所在的绝对路径。
执行如下命令生成libhello.so.0:
$sudo ldconfig
下面需要为libhello.so.0建立一个软链接,方便编译应用程序是链接,执行如下命令:
$ln -s libhello.so.0 libhello.so
然后,编写应用程序来调用动态库。
main.c文件:
#include "hello.h"
int main(void)
{
hello();
return 0;
}
执行下面的命令编译生成main的可执行文件:
$gcc main.c -L. -lhello -o main
注:没有重大升级(主版本号未更改),编译新版本的动态库后,执行$sudo ldconfig就可以进行动态库的升级。如果进行重大升级(更改主版本号),编译新版本的动态库后,执行$sudo ldconfig,生成新的so name文件,再执行$ln -s libhello.so.1 libhello.so(主版本号升级为1).如果想重新恢复为旧版本的动态库,只需要执行$ln -s libhello.so.0 libhello.so