运行库本身就是动态库吗?

Are runtime libraries inherently dynamic libraries?

我正在为一个带有 OpenMP 并行化程序的系统进行交叉编译,但是当我 运行 在目标上时,我得到错误:

无法加载库'libgomp.so.1'

环顾四周后,我发现它是一个 OpenMP 运行时间库。是否有任何静态 link 编译器主机上的库,或者它是否需要存在于目标机器上?如果可以静态 linked,那么 运行time 库与动态库有何不同?如果环境正确,是否可以静态或动态 link 任何库?

术语 "runtime library" 通常用于 运行 您的程序所需的标准库和环境。对于 C 程序,它是 C 标准库,可能还有一些其他特定于您的编译器的库,以及一些链接到您的程序以设置标准 C 环境的目标文件。

一个"runtime library"可以是一个动态库,甚至是多个动态库的集合。但也可以是一个或多个静态库。

Dynamic 库是提供 runtime 库的便捷方式,因为许多程序可能希望 link 反对这种图书馆。这就是动态 linking 和动态库在那里的原因 - 需要特定动态库的第一个进程将导致它被加载到内存中。以后这个动态库实例可以被很多进程复用

想象一下,如果您有数十个进程 运行,并且每个进程都静态地 link 反对说 C runtime 库。我认为与每个进程对单个 DLL link 的情况相比,内存消耗会显着增加。

在我看来,如果库将被许多不同的进程使用(例如 DirectX 可能是这样的库),那么将其作为动态库提供可能会更有效。否则,最好使用 static linking。

您可以通过提供某些 link 其他选项来选择性地静态 link 某些库。对于 libgomp 它将类似于:

gcc -o executable foo.o bar.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread -lother -llibs

-Wl,-static-Wl,-Bdynamic 之间列出的任何库都将被静态 linked。 -fopenmp 不应出现在 linking 命令中,因为它扩展为 linker 标志,这些标志附加在用户提供的选项之后,因此 libpthread 应该明确列出。这也意味着即使是简单的 OpenMP 程序也必须在两个单独的步骤中编译和 linked 才能使静态 linking 工作。

示例:

// foo.c
#include <stdio.h>
#include <omp.h>

int main(void)
{
   #pragma omp parallel
   printf("Hello world from thread %d\n", omp_get_thread_num());
   return 0;
}

繁体编译:

$ gcc -fopenmp -o foo foo.c
$ ldd foo
     linux-vdso.so.1 =>  (0x00007ffff5661000)
     libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x0000003bcfa00000)
     libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003bc2600000)
     libc.so.6 => /lib64/libc.so.6 (0x0000003bc1e00000)
     librt.so.1 => /lib64/librt.so.1 (0x0000003bc3200000)
     /lib64/ld-linux-x86-64.so.2 (0x0000003bc1a00000)

该程序是针对 libgomp 的 DSO 版本link编辑的。

完全静态 linking:

$ gcc -fopenmp -static -o foo foo.c
$ ldd foo
     not a dynamic executable

使用 -static 所有库都 link 静态地输入到可执行文件中。

libgomp 静态链接:

$ gcc -fopenmp -c foo.c
$ gcc -o foo foo.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread
$ ldd foo
     linux-vdso.so.1 =>  (0x00007ffdaaf61000)
     libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003bc2600000)
     libc.so.6 => /lib64/libc.so.6 (0x0000003bc1e00000)
     /lib64/ld-linux-x86-64.so.2 (0x0000003bc1a00000)

在这种情况下,保持静态 linked 对象的正确顺序很重要。如果 foo.o 放在 -lgomp 之后,将导致 link 错误结果:

$ gcc -o foo -Wl,-static -lgomp -Wl,-Bdynamic foo.o -lpthread
foo.o: In function `main':
foo.c:(.text+0x14): undefined reference to `GOMP_parallel_start'
foo.c:(.text+0x23): undefined reference to `GOMP_parallel_end'
foo.o: In function `main.omp_fn.0':
foo.c:(.text+0x3b): undefined reference to `omp_get_thread_num'
collect2: ld returned 1 exit status

任何由包含 OpenMP 结构的源代码产生的目标文件都应该放在之前 -lgomp.