找出加载的共享库的位置

找出加载的共享库的位置

我正在维护一个使用 Oracle 客户端库的 C 程序。在许多情况下,这些库期望ORACLE_HOME设置环境变量,如果没有它,就无法工作。

在我们的情况下,变量的值始终源自共享库本身的位置——而且我想从 C 代码中实现设置(使用putenv(3))。

但是,为此,我需要知道程序使用的特定共享库是从哪里加载的。因此, ifldd应用于可执行文件时,输出:

libc.so.7 => /lib/libc.so.7 (0x1021000)
libmeow.so.1 => /opt/meow/lib/libmeow.so.1

正在运行的进程本身如何发现它libmeow.so正在使用的 是从 加载的/opt/meow/lib

答案不必是普遍可移植的——只适用于 Linux 和 BSD 的东西就足够了。

答案1

对于 Linux,您可以通过伪文件读取和搜索/proc/<pid>/maps,其中<pid>来自self程序查看自身。它具有每个内存映射项的行,其中应包括每个共享库,例如

7f63c2c23000-7f63c2dd0000 r-xp 00000000 08:01 136321  /usr/lib64/libc-2.26.so

man proc详情请参阅。


还有一个 C API,可供程序遍历其正在使用的共享对象列表。看man dl_iterate_phdr。它提供了一个使用示例。对于您的用例,它就像这样简单:

#define _GNU_SOURCE
#include <link.h>
#include <stdlib.h>
#include <stdio.h>
static int callback(struct dl_phdr_info *info, size_t size, void *data){
    if(info->dlpi_name[0]!='\0')printf("%s\n", info->dlpi_name);
    return 0;
}
int main(int argc, char *argv[]) {
    dl_iterate_phdr(callback, NULL);
    exit(EXIT_SUCCESS);
}

答案2

如果您想获取库,可以使用命令找到链接的特定二进制文件ldd。例如:

$ldd /bin/cp
    linux-vdso.so.1 =>  (0x00007fffaf3ff000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003a06a00000)
    librt.so.1 => /lib64/librt.so.1 (0x0000003a06200000)
    libacl.so.1 => /lib64/libacl.so.1 (0x0000003a13000000)
    libattr.so.1 => /lib64/libattr.so.1 (0x0000003a0ea00000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003a05200000)
    libdl.so.2 => /lib64/libdl.so.2 (0x0000003a05a00000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003a04a00000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003a05600000)

从这里您可以过滤 Oracle 库并设置相应的ORACLE_HOME变量。所有这些都可以在脚本中完成,该脚本将使用已设置的变量运行您的程序。

相关内容