原文、
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.0
soname
format : libname.so.major-id
soname 与realname 有相同的major-id 但没有子版本号
运行时加载只是依赖于主版本号
soname 是符号链接,指向有最近子版本号的库
我们可以更改符号链接到最新版本的库
不同主版本号的库可以共存,可执行程序通过记录他的soname 即可
sample
libdemo.so.1 -> libdemo.so.1.0.2
libdemo.so.2 -> libdemo.so.2.0.1
libreadline.so.4 -> libreadline.so.4.0
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>
int
main(int argc, 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 */