程序解释器如何定位要加载的动态库的完整路径?

How program interpreter locates the full path of dynamic libraries to be loaded?

我正在尝试库的动态链接。这是我写的一个玩具程序:

// prog.c

#include<stdio.h>

int sum(int, int);
int diff(int, int);

int main(int argc, char* argv[]) {
    int a = 10, b = 5;
    
    printf("Sum: %d\n", sum(a, b));
    printf("Diff: %d\n", diff(a, b));
}
// sum.c

int sum(int a, int b) {
    return a + b;
}
// diff.c

int diff(int a, int b) {
    return a - b;
}

使用这些命令编译:

$ gcc -fPIC -c sum.c diff.c
$ gcc -shared -o libdtest.so sum.o diff.o
$ gcc prog.c -L. -l dtest

当我尝试 运行 时,它显示 ./a.out: error while loading shared libraries: libdtest.so: cannot open shared object file: No such file or directory。文件 libdtest.so 仍在我的文件夹中。这里有什么错误?

我用 readelf 读取了 a.out 文件。在动态部分,链接库是 libdtest.so 和 libc.so.6 。但我找不到任何关于他们完整路径的参考。程序解释器如何找到这些文件并加载它们?

动态库加载器有一组固定的路径用于搜索库。如果您有一个不在该集合中的自定义库,那么将找不到该库并且您会收到错误消息。

不幸的是,默认情况下,链接器不会自动将它所链接的库的路径添加到完成的可执行文件中。相反,您必须指定一个特殊选项来添加路径:-rpath.

您不能将 -rpath 直接与 gcc front-end 程序一起使用,这是一个 linker-specific 选项。您需要使用 -Wl 选项:

$ gcc prog.c -L. -l dtest -Wl,-rpath=$PWD

如果库已安装或将安装在 $PWD 以外的某个目录中,则您需要提供安装目录的实际(完整)路径。


其他可能的解决方案包括将路径添加到动态加载程序使用的集合中(不推荐用于不常见的路径),或设置 LD_LIBRARY_PATH 环境变量(根本不推荐)。