在C中运行时检测库功能

时间:2012-12-18 18:05:14

标签: c shared-libraries lazy-loading ld

我正在尝试在C中构建一个程序,它具有许多依赖于各种共享库的可选功能。

在我们的异构计算集群中,并非所有系统上的所有库都可用(或最新)。

示例是来自较新的glibc(sched_getcpu@@GLIBC_2.6__sched_cpucount@@GLIBC_2.6)或整个共享库的符号,这些符号可能可用也可能不可用(libnumalibR,{{1} })。

我知道我可以使用libpbs加载带有libdldlopen的符号,但是对于越来越多的符号(目前大约30个)这样做是很乏味的充其量。

据我所知,Linux中的共享库默认是延迟加载的,因此在实际使用之前不应该使用符号。

但如果我提前检查它,那么它在执行开始时失败:

dlsym

在包含所有库的编译系统上:

#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;
}

在另一个GLIBC版本较新的系统上:

$ icc test.c
$ ./a.out
10

如果我注释掉实际调用$ ./a.out ./a.out: /lib64/libc.so.6: version `GLIBC_2.6' not found (required by ./a.out) 的行,那么我会选择较小的系统:

sched_getcpu

那么,有没有办法强制只在使用时加载库,并在使用它们的块之前进行类似的检查?

1 个答案:

答案 0 :(得分:1)

不是glibc。这是一个自动防故障装置,它不会让你自己陷入困境。如果GLIBC_2.6符号未定义并查找,即使没有其他缺少的符号,您也可能从glibc(数据损坏和崩溃)获得垃圾结果,因为它不是向前兼容的。

如果你需要glibc级别的兼容性,你需要针对最低的通用版本进行构建。