c - 在 C 中运行时检测库特性

标签 c shared-libraries lazy-loading ld

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

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

示例是来自较新的 glibc 的符号(sched_getcpu@@GLIBC_2.6__sched_cpucount@@GLIBC_2.6)或可能可用也可能不可用的整个共享库( libnuma, libR, libpbs).

我知道我可以使用 libdl 通过 dlopendlsym 加载符号,但是这样做是为了越来越多的符号(目前大约 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;
}

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

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

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

$ ./a.out 
./a.out: /lib64/libc.so.6: version `GLIBC_2.6' not found (required by ./a.out)

如果我注释掉实际调用 sched_getcpu 的那一行,那么我会在较小的系统上取而代之:

$ ./a.out 
/lib64/libc.so.6: undefined symbol: sched_getcpu

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

最佳答案

不适用于 glibc。这是一个故障安全装置,它就位,这样你就不会搬起石头砸自己的脚。如果未定义和查找 GLIBC_2.6 符号,即使没有其他缺失的符号,您也可能会从 glibc 获得垃圾结果(数据损坏和崩溃),因为它不向前兼容。

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

关于c - 在 C 中运行时检测库特性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13938860/

相关文章:

c - 使用 mbed 写入 Matlab 和 C 之间的串行端口时遇到问题

c++ - g++ 5.5 不链接共享库

Angular 7 :- lazy loading routing issue

c# - Entity Framework 直接更新虚拟属性而不创建新记录

c - "unsupported for mov"GCC 内联汇编器

c - GCC:在获取地址时取消引用 ‘void *’ 指针

c++ - 在 Eclipse 环境中使用共享库 (SDSoC)

centos - 在服务器上使用/安装库,无需 sudo

.net - .NET 3.5 中的 EnumerateFiles() 等效项

c - 使用#define 来索引数组?