什么时候真正使用 dlopen()? dlopen() 是动态加载的意思吗?

问题描述 投票:0回答:1

我已经浏览了下面的链接,通过它我了解了如何创建和使用共享库。 https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html

Step 1: Compiling with Position Independent Code
$ gcc -c -Wall -Werror -fpic foo.c

Step 2: Creating a shared library from an object file
$ gcc -shared -o libfoo.so foo.o

Step 3: Linking with a shared library
$ gcc -L/home/username/foo -Wall -o test main.c -lfoo

Step 4: Making the library available at runtime
$ export LD_LIBRARY_PATH=/home/username/foo:$LD_LIBRARY_PATH
$ ./test
This is a shared library test...
Hello, I am a shared library

但是,我有几个问题:

  1. 在给定的链接中,没有使用打开共享库所需的 dlopen()。这段代码在没有 dlopen() 调用的情况下如何工作?
  2. 什么时候真正使用 dlopen()?
  3. 我可以在没有 .so 文件可用的情况下编译程序吗(程序有对该共享库的函数调用)?
  4. dlopen() 是否意味着动态加载,而上面链接中的示例(步骤 3)是否意味着静态加载?如果是,那么在动态加载的情况下,链接步骤(步骤3)有什么区别吗?
linker shared-libraries dlopen dynamic-loading .so
1个回答
12
投票

动态库

当我们将应用程序链接到共享库时,链接器会留下一些存根(未解析的符号),以便在应用程序加载时填充。这些存根需要在运行时或应用程序加载时由称为动态链接器的工具填充。

共享库的加载有两种类型,

  1. 动态链接库

这里有一个程序与共享库链接,内核在执行时加载该库(如果它不在内存中)。 这在提到的链接中进行了解释。

  1. 动态加载库

对于创建“插件”架构很有用。 顾名思义,动态加载是指按需加载库并在执行期间链接。 程序通过调用库函数来完全控制。 这是使用 dlopen()、dlsym()、dlclose() 完成的。 dlopen() 函数打开一个库并准备使用。 通过此系统调用,可以打开共享库并使用其中的函数,而无需与其链接。你的程序刚刚启动,当它发现需要使用特定库中的函数时,它会调用 dlopen() 打开该库。如果该库在系统上不可用,则该函数将返回 NULL,并且由您(程序员)来处理。你可以让程序优雅地死掉。

深度学习示例: 此示例加载数学库并打印 2.0 的余弦,并在每一步检查错误(推荐):

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    void *handle;
    double (*cosine)(double);
    char *error;

    handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
    if (!handle) {
        fputs (dlerror(), stderr);
        exit(1);
    }

    cosine = dlsym(handle, "cos");
    if ((error = dlerror()) != NULL)  {
        fputs(error, stderr);
        exit(1);
    }

    printf ("%f\n", (*cosine)(2.0));
    dlclose(handle);
}

编译 DL 源代码时使用 -rdynamic。

例如。 gcc -rdynamic -o progdl progdl.c -ldl

© www.soinside.com 2019 - 2024. All rights reserved.