我正在维护一个使用 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
变量。所有这些都可以在脚本中完成,该脚本将使用已设置的变量运行您的程序。