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

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

无法加载库’libgomp.so.1′

环顾四周后,我发现它是一个OpenMP运行时库。 有没有在编译器主机上静态链接库,还是需要在目标机器上存在? 如果它可以静态链接,那么是什么使运行时库与动态库不同? 如果环境正确,可以静态或动态链接任何库吗?

您可以通过提供某些链接器选项来选择性地静态链接某些库。 对于libgomp ,它将是这样的:

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

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

例:

 // foo.c #include  #include  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版本相关libgomp

完全静态链接:

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

使用-static所有库都静态链接到可执行文件中。

仅静态链接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) 

在这种情况下,保持静态链接对象的正确顺序很重要。 如果在-lgomp之后放置foo.o-lgomp出现链接错误:

 $ 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 之前

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

“运行时库” 可以是动态库,甚至可以是多个动态库的集合。 但它也可以是一个或多个静态库。

动态库是提供运行时库的便捷方式,因为许多程序可能希望链接到这样的库。 这就是动态链接和动态库在那里的原因 – 第一个需要特定动态库的进程将导致它被加载到内存中。 之后,这个动态库实例可以被许多进程重用。

想象一下,如果你有几十个进程在运行,并且每个进程都与C runtime库静态链接。 我假设与每个进程链接单个DLL的情况相比,内存消耗会相当显着增长。

在我看来,如果库将被许多不同的进程使用(例如DirectX可能是这样的库),将它作为动态库提供可能更有效。 否则,静态链接是优选的。