Ser*_* L. 5 c lazy-loading shared-libraries ld
我正在尝试在C中构建一个程序,它具有许多依赖于各种共享库的可选功能.
在我们的异构计算集群中,并非所有这些库都可在所有系统上使用(或更新).
实例是从较新的glibc(符号sched_getcpu@@GLIBC_2.6,__sched_cpucount@@GLIBC_2.6)或整个共享库其可以是或可以不是可用的(libnuma,libR,libpbs).
我知道,我可以使用libdl与加载符号dlopen和dlsym,但这样做的(目前约为30)数量不断增长的符号是乏味的最好的.
据我所知,Linux中的共享库默认是延迟加载的,因此在实际使用之前不应该使用符号.
但是如果我尝试提前检查它,那么它在执行开始时失败:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
#include <sched.h>
int main() {
void *lib_handle;
int (*fn)(void);
int x;
char *error;
lib_handle = dlopen("libc.so.6", RTLD_LAZY);
if (!lib_handle)
{
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
fn = dlsym(lib_handle, "sched_getcpu");
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error);
exit(1);
}
printf("%d\n", sched_getcpu());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在包含所有库的编译系统上:
$ icc test.c
$ ./a.out
10
Run Code Online (Sandbox Code Playgroud)
在另一个具有较新版本的GLIBC的系统上:
$ ./a.out
./a.out: /lib64/libc.so.6: version `GLIBC_2.6' not found (required by ./a.out)
Run Code Online (Sandbox Code Playgroud)
如果我注释掉实际调用的行,sched_getcpu那么我会改为使用较小的系统:
$ ./a.out
/lib64/libc.so.6: undefined symbol: sched_getcpu
Run Code Online (Sandbox Code Playgroud)
那么,有没有办法强制库只在使用时加载,并在使用它们的块之前进行类似的检查?
不适合 glibc。这是一个自动保险装置,它安装到位,这样您就不会搬起石头砸自己的脚。如果GLIBC_2.6未定义并查找该符号,即使没有其他丢失的符号,您也可能会从 glibc 获得垃圾结果(数据损坏和崩溃),因为它不向前兼容。
如果您需要 glibc 级别的兼容性,则需要针对最低的通用版本进行构建。