原文、
shared library
compatible vs incompatible
compatible library
函数的工作场景没有变化
- 所有的函数对全局变量和返回参数产生相同的影响
- 所有的函数继续返回相同的结果值
- 提升性能 fix bugs
没有api 被删除 - 可以有新的api加入
export 的结构体没有变化
违反以上各条的library 都是incompatible
library verison and naming
如果新版本的库与老版本的库是兼容的,我们需要修改minor version number
如果新版本的库与老版本的库是不兼容的,我们需要修改major version number
real name
real name 是有库代码的文件的名字
format: libxxxx.so.major-id.minor-id
major-id : 是不断递增的数字 用来标记不兼容的库
minor-id: 用来区分在相同major-id下不同的但是兼容的子版本库
通常情况下,子版本号可以是一个数字或者用点分隔开的两个数字,第一个表示子版本号,第二个表示patch level 或者 revision number
libdemo.so.1.0.1 libdemo.so.1.0.2 libdemo.so.2.0.1 libreadline.so.4.0soname
format : libname.so.major-id
soname 与realname 有相同的major-id 但没有子版本号
运行时加载只是依赖于主版本号
soname 是符号链接,指向有最近子版本号的库
我们可以更改符号链接到最新版本的库
不同主版本号的库可以共存,可执行程序通过记录他的soname 即可
sample
libdemo.so.1->libdemo.so.1.0.2libdemo.so.2->libdemo.so.2.0.1libreadline.so.4->libreadline.so.4.0在创建动态链接库的时候,可以给ld 传-soname=name这个参数来指定库的soname,在链接的时候NEEDED中记录的就是soname.
linker name
format: libname.so
目标是能够提供一种版本独立的链接命令,它可以自动选择正确版本的库。
创建符号链接指向realname或者soname
动态加载库
dlopen api:
Four key functions: dlopen(), dlerror(), dlsym(), and dlclose().
/* Usage: dynload lib-path func-name */#include<stdio.h>#include<stdlib.h>#include<dlfcn.h>intmain(intargc,char*argv[]){void*libHandle;/* Handle for shared library */void(*funcp)(void);/* Pointer to function with no args */char*err;if(argc!=3){/* Check command line arguments */fprintf(stderr,"Usage: %s lib-path func-name\n",argv[0]);exit(EXIT_FAILURE);}/* if *//* Load the shared library and get a handle for later use */libHandle=dlopen(argv[1],RTLD_NOW);if(libHandle==NULL){fprintf(stderr,"Error on dlopen: %s\n",dlerror());exit(EXIT_FAILURE);}/* if *//* Get a pointer to named function inside library */(void)dlerror();/* Clear dlerror() *//* The strange cast below is required by C99, which forbids assignment between a function pointer and void * */*(void**)(&funcp)=dlsym(libHandle,argv[2]);err=dlerror();if(err!=NULL){/* Non-NULL from dlerror() means we got error */fprintf(stderr,"Error on dlsym: %s\n",err);exit(EXIT_FAILURE);}/* if *//* If the function address is non-NULL try calling it */if(funcp==NULL)printf("%s is NULL\n",argv[2]);else(*funcp)();/* And close the library */dlclose(libHandle);exit(EXIT_SUCCESS);}/* main */