深入分析linux下 动态库的显性调用(dlopen)和隐性调用区别

本文详细介绍了在Linux环境下,编程时使用静态库、动态库(隐性调用与显性调用)的四种方式,并通过一个计算库实例分析了它们对内存的影响。静态库与源码编译方式占用内存相同,隐性动态调用在程序启动时即加载库,而显性动态调用在dlopen后才加载库,提供了更灵活的插件机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 前言

在linux环境下编程,我们如果想要使用第三方的库,基本上有以下几种方式:

  • 1、将第三方库的源码合并到我们的工程项目代码中,一起编译。
  • 2、将第三方库编译成静态库(xxx.a),我们在使用时,在Makefile中引用该静态库。
  • 3、将第三方库编译成动态库(xxx.so), 我们在使用时,隐性调用该动态库,具体表现为需要 在程序中包含动态库的 头文件,同时需要在/usr/lib路径下,存放动态库文件,以便程序调用。
  • 4、将第三方库编译成动态库(xxx.so), 我们在使用时,显性调用该动态库,在程序中,不需要包含动态库的头文件,使用 dlopen、dlsym等接口函数调用该动态库。

这4种方式:

  • 第1和2种,本质上是一样的,使用静态库,编译时,会将静态库的内容合并到工程代码中,唯一区别的是当我们拿不到第三方库的源码时,可以直接使用静态库,相当于使用一个黑盒子,静态库提供接口。
  • 第3和4种方式,我们常用的是第3种方式,也就是隐性调用,但是显性调用一种程序插件的概念,随用随加载,不用不加载。

2. 显性调用和隐性调用区别

这里我们先说结论:

  • 隐性调用:需要提前将动态库xxx.so 拷贝到 相关目录下,不管程序是否真正使用动态库,执行前会检查该动态库,如果检测不到动态库,会报错。
  • 隐性调用,程序一旦执行,会把动态库读到内存中,而不管是否会运行到动态库部分,相当于一刀切。
  • 显性调用,如果程序没有运行到dlopen,动态库文件xxx.so 是不需要拷贝到相关目录下的,程序只有在执行到dlopen时,才会检查该动态库,是一种插件形式,随用随调用。
  • 显性调用,程序开始运行后,不会立刻读取动态库到内存中,而是直行道dlopen时,才会将动态库拷贝到内存中。
名称使用方式动态库文件内存其他
隐性调用引用动态库头文件需要提前拷贝到/usr/lib/目录,否则程序无法执行程序开始执行,不管是否用到动态库功能,都会将动态库读到内存中不会额外调用插件库
显性调用不需要引用动态库头文件,但是需要引用<dlfcn.h>不一定,如果程序不会执行到动态库功能,则不需要拷贝,即便使用,也可以使用绝对路径来使用,不需要拷贝到/usr/lib/目录下只有程序执行到dlopen时,才会将动态库读入内存会额外调用linux插件库,来支持显性调用

3. 测试

测试的思路就是对比,对比源码、静态库、动态库显性调用、动态库隐性调用,这4种方式的内存占比情况。

3.1 场景

我们实现一种简单的场景,编写一个 加、减、乘、除、打印等功能的 计算库,主程序中调用该库,计算库源码如下:

#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>


const char *CA_crt = \
{
    \
    "-----BEGIN CERTIFICATE-----\r\n"
    "MIIDkzCCAnugAwIBAgIJAI436FANVXhYMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV\r\n" \
    "BAYTAkNOMQ4wDAYDVQQIDAVIZWJlaTERMA8GA1UEBwwITGFuZ2ZhbmcxDDAKBgNV\r\n" \
    "BAoMA0VOTjEOMAwGA1UECwwFRU5ORVcxDzANBgNVBAMMBklvVCBDQTAgFw0yMTAz\r\n" \
    "MTEwODMyMjRaGA8yMTIxMDIxNTA4MzIyNFowXzELMAkGA1UEBhMCQ04xDjAMBgNV\r\n" \
    "BAgMBUhlYmVpMREwDwYDVQQHDAhMYW5nZmFuZzEMMAoGA1UECgwDRU5OMQ4wDAYD\r\n" \
    "VQQLDAVFTk5FVzEPMA0GA1UEAwwGSW9UIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC\r\n" \
    "AQ8AMIIBCgKCAQEAzeteOYou2GlZys4lEo+ypdXYCmpayqSdpZGIaVojLNNYqoQc\r\n" \
    "kbghLhxzJxlB72lMc3zOPrYHyG/pe9Abh198sHSU0FInjr6nTx07rUy5SsIKQNIY\r\n" \
    "sih8pxVH+7CDp9X+BNhRWGbobE0KnMO+U5XjR4+b7yGDGfaWzBxIaADYJDnbcWEs\r\n" \
    "14EfSnADE0I9A2AyqLgZTpr6sj0A8ybowl/SgJW7wT+yrymNbNlzYDZKN4ow1376\r\n" \
    "PsXiwtnN0TO2g3x9bYvIjFRpEzcyoW2/eab81ztS81YE3RslfWh74lpviOoB8z7M\r\n" \
    "Va3dQIJrsCvRjDkWueuDrw2MmC1R8tB4HtqZxQIDAQABo1AwTjAdBgNVHQ4EFgQU\r\n" \
    "h06iXX7GqtF5T19AZzkXhLSSaz4wHwYDVR0jBBgwFoAUh06iXX7GqtF5T19AZzkX\r\n" \
    "hLSSaz4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAuC/J3nO01YxS\r\n" \
    "TZuhXtFio3AGkQNptFlsGjWyzxLyH2oJN7PI6KpI2XhteUzRfUN2rx7F9uwpFig8\r\n" \
    "yDphOU7fesbvRsAKkb6HhDgeMKcuPrKOM2FMj6JVcyHERJ5J7MaqcRVAS948F54n\r\n" \
    "fCAOIfvkd8Y8EmxptDnbyJ7gTwJ4mAYuXJzLtVaEZqMcAvvFdJgKHHNJhl7SqfO3\r\n" \
    "c9JJhepx0djWwR4coMc66Fe3X9lDdmhGt/t6TXxI09qGxecpj8p/VuRQ02gcLyZW\r\n" \
    "139Yg2JpWUftmyITvBCW1fNM1Uf1GGu6tsFibE+DcwhGNJ0rbBP/EzSFg1trAkUN\r\n" \
    "svRnMOVUuQ==\r\n" \
    "-----END CERTIFICATE-----"
};


int add(int a,int b)
{
    return (a + b);
}

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

int mul(int a, int b)
{
    return (a * b);
}

int div(int a, int b)
{
    return (a / b);
}

void print_CA_info(void)
{
    printf("%s", CA_crt);
}

注: 上述代码中,包含了一个CA证书,目的是为了增加这个 动态库的体积,方便后面的比较,否则动态库太小的话,看不出区别。

测试代码逻辑:

int main(void)
{
    printf("start wait 60s...\n");
    sleep(60);
    printf("will return in 20...\n");
    print_CA_info();
    sleep(20);
    return 0;
}

上述代码中,有两部分组成,前一部分是未执行动态库内容,进行等待,后一部分则是执行动态库内的函数,这样做的目的是为了 分析 显性调用的 dlopen 前后内存区别。

3.2 源码使用

直接将动态库的源码合并到测试程序里,进行编译,运行,内存监控如下:

ubuntu@VM-0-17-ubuntu:~$ ps -ef|grep test-src
ubuntu    3826  3082  0 11:03 pts/3    00:00:00 ./test-src
ubuntu    3856  3194  0 11:03 pts/4    00:00:00 grep test-src
ubuntu@VM-0-17-ubuntu:~$ pmap -x 3826
3826:   ./test-src
Address           Kbytes     RSS   Dirty Mode  Mapping
000055662853e000       4       4       0 r-x-- test-src
000055662853e000       0       0       0 r-x-- test-src
000055662873f000       4       4       4 r---- test-src
000055662873f000       0       0       0 r---- test-src
0000556628740000       4       4       4 rw--- test-src
0000556628740000       0       0       0 rw--- test-src
000055662a2c3000     132       4       4 rw---   [ anon ]
000055662a2c3000       0       0       0 rw---   [ anon ]
00007f1b03aed000    1948    1164       0 r-x-- libc-2.27.so
00007f1b03aed000       0       0       0 r-x-- libc-2.27.so
00007f1b03cd4000    2048       0       0 ----- libc-2.27.so
00007f1b03cd4000       0       0       0 ----- libc-2.27.so
00007f1b03ed4000      16      16      16 r---- libc-2.27.so
00007f1b03ed4000       0       0       0 r---- libc-2.27.so
00007f1b03ed8000       8       8       8 rw--- libc-2.27.so
00007f1b03ed8000       0       0       0 rw--- libc-2.27.so
00007f1b03eda000      16      12      12 rw---   [ anon ]
00007f1b03eda000       0       0       0 rw---   [ anon ]
00007f1b03ede000     164     164       0 r-x-- ld-2.27.so
00007f1b03ede000       0       0       0 r-x-- ld-2.27.so
00007f1b040fb000       8       8       8 rw---   [ anon ]
00007f1b040fb000       0       0       0 rw---   [ anon ]
00007f1b04107000       4       4       4 r---- ld-2.27.so
00007f1b04107000       0       0       0 r---- ld-2.27.so
00007f1b04108000       4       4       4 rw--- ld-2.27.so
00007f1b04108000       0       0       0 rw--- ld-2.27.so
00007f1b04109000       4       4       4 rw---   [ anon ]
00007f1b04109000       0       0       0 rw---   [ anon ]
00007ffecec06000     132      12      12 rw---   [ stack ]
00007ffecec06000       0       0       0 rw---   [ stack ]
00007ffeceddd000      12       0       0 r----   [ anon ]
00007ffeceddd000       0       0       0 r----   [ anon ]
00007ffecede0000       8       4       0 r-x--   [ anon ]
00007ffecede0000       0       0       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
ffffffffff600000       0       0       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB            4520    1416      80

可以看到 占用内存 约 1416kb

3.3 静态库调用

将共享库编译成静态库libcalculate.a,然后在编译测试程序时,引用该静态库,具体的编译步骤这里就省略,运行,监控内存如下:

ubuntu@VM-0-17-ubuntu:~$ ps -ef|grep test-hid-a
ubuntu    4773  3082  0 11:09 pts/3    00:00:00 ./test-hid-a
ubuntu    4794  3194  0 11:09 pts/4    00:00:00 grep test-hid-a
ubuntu@VM-0-17-ubuntu:~$ pmap -x 4773
4773:   ./test-hid-a
Address           Kbytes     RSS   Dirty Mode  Mapping
000055b2814cd000       4       4       0 r-x-- test-hid-a
000055b2814cd000       0       0       0 r-x-- test-hid-a
000055b2816ce000       4       4       4 r---- test-hid-a
000055b2816ce000       0       0       0 r---- test-hid-a
000055b2816cf000       4       4       4 rw--- test-hid-a
000055b2816cf000       0       0       0 rw--- test-hid-a
000055b282710000     132       4       4 rw---   [ anon ]
000055b282710000       0       0       0 rw---   [ anon ]
00007eff6c989000    1948    1180       0 r-x-- libc-2.27.so
00007eff6c989000       0       0       0 r-x-- libc-2.27.so
00007eff6cb70000    2048       0       0 ----- libc-2.27.so
00007eff6cb70000       0       0       0 ----- libc-2.27.so
00007eff6cd70000      16      16      16 r---- libc-2.27.so
00007eff6cd70000       0       0       0 r---- libc-2.27.so
00007eff6cd74000       8       8       8 rw--- libc-2.27.so
00007eff6cd74000       0       0       0 rw--- libc-2.27.so
00007eff6cd76000      16      12      12 rw---   [ anon ]
00007eff6cd76000       0       0       0 rw---   [ anon ]
00007eff6cd7a000     164     152       0 r-x-- ld-2.27.so
00007eff6cd7a000       0       0       0 r-x-- ld-2.27.so
00007eff6cf97000       8       8       8 rw---   [ anon ]
00007eff6cf97000       0       0       0 rw---   [ anon ]
00007eff6cfa3000       4       4       4 r---- ld-2.27.so
00007eff6cfa3000       0       0       0 r---- ld-2.27.so
00007eff6cfa4000       4       4       4 rw--- ld-2.27.so
00007eff6cfa4000       0       0       0 rw--- ld-2.27.so
00007eff6cfa5000       4       4       4 rw---   [ anon ]
00007eff6cfa5000       0       0       0 rw---   [ anon ]
00007ffdc50e7000     132       8       8 rw---   [ stack ]
00007ffdc50e7000       0       0       0 rw---   [ stack ]
00007ffdc51af000      12       0       0 r----   [ anon ]
00007ffdc51af000       0       0       0 r----   [ anon ]
00007ffdc51b2000       8       4       0 r-x--   [ anon ]
00007ffdc51b2000       0       0       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
ffffffffff600000       0       0       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB            4520    1416      76

可以看到,静态调用占用的内存与 源码方式是一样的,这个也能证明静态调用的特点。

3.4 隐性动态调用

将共享库编译成libcalculate.so,然后我们在测试程序中,引用动态库头文件,编译,同时将动态库拷贝到/usr/lib/下,运行,监控如下:

ubuntu@VM-0-17-ubuntu:~$ ps -ef|grep test-hid
ubuntu    5433  3082  0 11:13 pts/3    00:00:00 ./test-hid
ubuntu    5480  3194  0 11:13 pts/4    00:00:00 grep test-hid
ubuntu@VM-0-17-ubuntu:~$ pmap -x 5433
5433:   ./test-hid
Address           Kbytes     RSS   Dirty Mode  Mapping
00005564e6e88000       4       4       0 r-x-- test-hid
00005564e6e88000       0       0       0 r-x-- test-hid
00005564e7088000       4       4       4 r---- test-hid
00005564e7088000       0       0       0 r---- test-hid
00005564e7089000       4       4       4 rw--- test-hid
00005564e7089000       0       0       0 rw--- test-hid
00005564e79d1000     132       4       4 rw---   [ anon ]
00005564e79d1000       0       0       0 rw---   [ anon ]
00007f64bfd05000    1948    1068       0 r-x-- libc-2.27.so
00007f64bfd05000       0       0       0 r-x-- libc-2.27.so
00007f64bfeec000    2048       0       0 ----- libc-2.27.so
00007f64bfeec000       0       0       0 ----- libc-2.27.so
00007f64c00ec000      16      16      16 r---- libc-2.27.so
00007f64c00ec000       0       0       0 r---- libc-2.27.so
00007f64c00f0000       8       8       8 rw--- libc-2.27.so
00007f64c00f0000       0       0       0 rw--- libc-2.27.so
00007f64c00f2000      16      12      12 rw---   [ anon ]
00007f64c00f2000       0       0       0 rw---   [ anon ]
00007f64c00f6000       4       4       0 r-x-- libcalculate.so
00007f64c00f6000       0       0       0 r-x-- libcalculate.so
00007f64c00f7000    2044       0       0 ----- libcalculate.so
00007f64c00f7000       0       0       0 ----- libcalculate.so
00007f64c02f6000       4       4       4 r---- libcalculate.so
00007f64c02f6000       0       0       0 r---- libcalculate.so
00007f64c02f7000       4       4       4 rw--- libcalculate.so
00007f64c02f7000       0       0       0 rw--- libcalculate.so
00007f64c02f8000     164     160       0 r-x-- ld-2.27.so
00007f64c02f8000       0       0       0 r-x-- ld-2.27.so
00007f64c0512000      20      12      12 rw---   [ anon ]
00007f64c0512000       0       0       0 rw---   [ anon ]
00007f64c0521000       4       4       4 r---- ld-2.27.so
00007f64c0521000       0       0       0 r---- ld-2.27.so
00007f64c0522000       4       4       4 rw--- ld-2.27.so
00007f64c0522000       0       0       0 rw--- ld-2.27.so
00007f64c0523000       4       4       4 rw---   [ anon ]
00007f64c0523000       0       0       0 rw---   [ anon ]
00007ffc8b435000     132      12      12 rw---   [ stack ]
00007ffc8b435000       0       0       0 rw---   [ stack ]
00007ffc8b4ef000      12       0       0 r----   [ anon ]
00007ffc8b4ef000       0       0       0 r----   [ anon ]
00007ffc8b4f2000       8       4       0 r-x--   [ anon ]
00007ffc8b4f2000       0       0       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
ffffffffff600000       0       0       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB            6588    1332      92

上述监控可以看到,内存使用基本上没有太大变化,不过内存中已经有了 libcalculate.so 了。

3.5 显性动态调用

显性动态调用测试代码如下:

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

#define LIB_CALCULATE_PATH  "./tmp/libcalculate.so"

typedef int (*CALC_FUNC)(int, int);

typedef void (*CALC_FUNC1)(void);

int main(void)
{
    void *handle;
    char *error;
    CALC_FUNC calc_func = NULL;    
    CALC_FUNC1 print_func = NULL;

    printf("start wait 60s...\n");
    sleep(60);
    printf("will return in 20...\n");

    handle = dlopen(LIB_CALCULATE_PATH, RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        return -1;
    }

    dlerror();

    *(void **) (&calc_func) = dlsym(handle, "add");
    if ((error = dlerror()) != NULL)  {
        fprintf(stderr, "%s\n", error);
        return -1;
    }
    
    printf("add: %d\n", (*calc_func)(2,7));

    print_func = (CALC_FUNC1)dlsym(handle, "print_CA_info");
    print_func();

    sleep(20);
    return 0;
}

编译、运行、监控如下:

ubuntu@VM-0-17-ubuntu:~$ ps -ef|grep test-obvious
ubuntu    6139  3082  0 11:18 pts/3    00:00:00 ./test-obvious
ubuntu    6156  3194  0 11:18 pts/4    00:00:00 grep test-obvious
ubuntu@VM-0-17-ubuntu:~$ pmap -x 6139
6139:   ./test-obvious
Address           Kbytes     RSS   Dirty Mode  Mapping
00005561450f1000       4       4       0 r-x-- test-obvious
00005561450f1000       0       0       0 r-x-- test-obvious
00005561452f2000       4       4       4 r---- test-obvious
00005561452f2000       0       0       0 r---- test-obvious
00005561452f3000       4       4       4 rw--- test-obvious
00005561452f3000       0       0       0 rw--- test-obvious
00005561459a5000     132       4       4 rw---   [ anon ]
00005561459a5000       0       0       0 rw---   [ anon ]
00007f1c0abc2000    1948    1080       0 r-x-- libc-2.27.so
00007f1c0abc2000       0       0       0 r-x-- libc-2.27.so
00007f1c0ada9000    2048       0       0 ----- libc-2.27.so
00007f1c0ada9000       0       0       0 ----- libc-2.27.so
00007f1c0afa9000      16      16      16 r---- libc-2.27.so
00007f1c0afa9000       0       0       0 r---- libc-2.27.so
00007f1c0afad000       8       8       8 rw--- libc-2.27.so
00007f1c0afad000       0       0       0 rw--- libc-2.27.so
00007f1c0afaf000      16      12      12 rw---   [ anon ]
00007f1c0afaf000       0       0       0 rw---   [ anon ]
00007f1c0afb3000      12      12       0 r-x-- libdl-2.27.so
00007f1c0afb3000       0       0       0 r-x-- libdl-2.27.so
00007f1c0afb6000    2044       0       0 ----- libdl-2.27.so
00007f1c0afb6000       0       0       0 ----- libdl-2.27.so
00007f1c0b1b5000       4       4       4 r---- libdl-2.27.so
00007f1c0b1b5000       0       0       0 r---- libdl-2.27.so
00007f1c0b1b6000       4       4       4 rw--- libdl-2.27.so
00007f1c0b1b6000       0       0       0 rw--- libdl-2.27.so
00007f1c0b1b7000     164     164       0 r-x-- ld-2.27.so
00007f1c0b1b7000       0       0       0 r-x-- ld-2.27.so
00007f1c0b3d1000      20      12      12 rw---   [ anon ]
00007f1c0b3d1000       0       0       0 rw---   [ anon ]
00007f1c0b3e0000       4       4       4 r---- ld-2.27.so
00007f1c0b3e0000       0       0       0 r---- ld-2.27.so
00007f1c0b3e1000       4       4       4 rw--- ld-2.27.so
00007f1c0b3e1000       0       0       0 rw--- ld-2.27.so
00007f1c0b3e2000       4       4       4 rw---   [ anon ]
00007f1c0b3e2000       0       0       0 rw---   [ anon ]
00007fffe6879000     132      16      16 rw---   [ stack ]
00007fffe6879000       0       0       0 rw---   [ stack ]
00007fffe69a7000      12       0       0 r----   [ anon ]
00007fffe69a7000       0       0       0 r----   [ anon ]
00007fffe69aa000       8       4       0 r-x--   [ anon ]
00007fffe69aa000       0       0       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
ffffffffff600000       0       0       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB            6596    1360      96
ubuntu@VM-0-17-ubuntu:~$ pmap -x 6139
6139:   ./test-obvious
Address           Kbytes     RSS   Dirty Mode  Mapping
00005561450f1000       4       4       0 r-x-- test-obvious
00005561450f1000       0       0       0 r-x-- test-obvious
00005561452f2000       4       4       4 r---- test-obvious
00005561452f2000       0       0       0 r---- test-obvious
00005561452f3000       4       4       4 rw--- test-obvious
00005561452f3000       0       0       0 rw--- test-obvious
00005561459a5000     132       4       4 rw---   [ anon ]
00005561459a5000       0       0       0 rw---   [ anon ]
00007f1c0a9c0000       4       4       0 r-x-- libcalculate.so
00007f1c0a9c0000       0       0       0 r-x-- libcalculate.so
00007f1c0a9c1000    2044       0       0 ----- libcalculate.so
00007f1c0a9c1000       0       0       0 ----- libcalculate.so
00007f1c0abc0000       4       4       4 r---- libcalculate.so
00007f1c0abc0000       0       0       0 r---- libcalculate.so
00007f1c0abc1000       4       4       4 rw--- libcalculate.so
00007f1c0abc1000       0       0       0 rw--- libcalculate.so
00007f1c0abc2000    1948    1272       0 r-x-- libc-2.27.so
00007f1c0abc2000       0       0       0 r-x-- libc-2.27.so
00007f1c0ada9000    2048       0       0 ----- libc-2.27.so
00007f1c0ada9000       0       0       0 ----- libc-2.27.so
00007f1c0afa9000      16      16      16 r---- libc-2.27.so
00007f1c0afa9000       0       0       0 r---- libc-2.27.so
00007f1c0afad000       8       8       8 rw--- libc-2.27.so
00007f1c0afad000       0       0       0 rw--- libc-2.27.so
00007f1c0afaf000      16      12      12 rw---   [ anon ]
00007f1c0afaf000       0       0       0 rw---   [ anon ]
00007f1c0afb3000      12      12       0 r-x-- libdl-2.27.so
00007f1c0afb3000       0       0       0 r-x-- libdl-2.27.so
00007f1c0afb6000    2044       0       0 ----- libdl-2.27.so
00007f1c0afb6000       0       0       0 ----- libdl-2.27.so
00007f1c0b1b5000       4       4       4 r---- libdl-2.27.so
00007f1c0b1b5000       0       0       0 r---- libdl-2.27.so
00007f1c0b1b6000       4       4       4 rw--- libdl-2.27.so
00007f1c0b1b6000       0       0       0 rw--- libdl-2.27.so
00007f1c0b1b7000     164     164       0 r-x-- ld-2.27.so
00007f1c0b1b7000       0       0       0 r-x-- ld-2.27.so
00007f1c0b3d1000      20      12      12 rw---   [ anon ]
00007f1c0b3d1000       0       0       0 rw---   [ anon ]
00007f1c0b3e0000       4       4       4 r---- ld-2.27.so
00007f1c0b3e0000       0       0       0 r---- ld-2.27.so
00007f1c0b3e1000       4       4       4 rw--- ld-2.27.so
00007f1c0b3e1000       0       0       0 rw--- ld-2.27.so
00007f1c0b3e2000       4       4       4 rw---   [ anon ]
00007f1c0b3e2000       0       0       0 rw---   [ anon ]
00007fffe6879000     132      16      16 rw---   [ stack ]
00007fffe6879000       0       0       0 rw---   [ stack ]
00007fffe69a7000      12       0       0 r----   [ anon ]
00007fffe69a7000       0       0       0 r----   [ anon ]
00007fffe69aa000       8       4       0 r-x--   [ anon ]
00007fffe69aa000       0       0       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
ffffffffff600000       0       0       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB            8652    1564     104

上面的监控信息我们可以清楚的看到:

  • 在显性调用中,dlopen之前, libcalculate.so并没有读入到内存中,但是因为使用了插件机制,将libdl-2.27.so 插件库读入内存了,也是因为这个原因,导致内存并没有想象中的那么小。
  • dlopen之后,libcalculate.so 被读入内存中,内存也增加到了1564kb。

3.6 内存对比

方式内存
源码1416Kb
静态库1416Kb
隐性动态库1332
显性动态库调用前1360Kb/调用后1564Kb

小结

  • 显性调用更多的是体现在“插件”的思想,使用起来更加灵活,比如大的工程项目中,同样一套代码,提供不一样的功能时,为了节省内存、磁盘容量,可以按需加载。
  • 在使用方式上,显性调用相比隐性调用,略复杂,需要增加额外的转换代码,而隐性调用,只需要包含动态库头文件,在代码中,直接调用API即可。
  • 在生产程序中,如果对内存或磁盘、启动速度没有严苛的要求,尽量使用隐形调用,方便程序编写和维护。
Linux中,Qt Creator是一个强大的集成开发环境,用于开发跨平台的应用程序。在使用Qt Creator创建调用动态库时,需要经过以下几个步骤: 1. 首先,在Qt Creator中新建一个工程。选择“Dynamic Library”作为项目类型。 2. 在工程文件中,定义需要暴露给其他程序使用的函数类。可以在.h头文件中声明函数类的接口,并在.cpp源文件中实现相应的功能。 3. 编译生成动态库文件。在Qt Creator中,可以点击“构建”按钮编译链接生成动态库文件。生成的动态库文件一般以.so(shared object)为扩展名。 4. 创建一个新的可执行程序项目,并引用该动态库。在新的项目中,需要在.pro文件中添加对动态库的依赖关系。例如,可以使用LIBS += -L/path/to/library -lmylibrary来指定动态库的路径名称。 5. 在可执行程序中调用动态库中的函数或类。在主函数或其他需要使用动态库的地方,可以直接调用动态库中定义的函数或类,实现相应的功能。 值得注意的是,动态库调用中还需要注意以下几点: 1. 在调用动态库函数时,需要先加载动态库。可以使用dlopen函数加载动态库文件,并使用dlsym函数获取需要调用的函数指针。 2. 调用动态库中的函数时,需要根据函数的参数类型进行适当的类型转换。因为动态库函数的参数类型可能与调用者的类型不完全匹配。 3. 在完成动态库的使用后,需要使用dlclose函数关闭对动态库的引用,释放相关资源。 总结来说,使用Qt Creator在Linux中创建调用动态库需要进行项目的设置、编译生成动态库文件,然后在其他项目中引用动态库调用其中定义的函数或类。同时,还需要注意动态库的加载关闭过程,以确保正确使用动态库功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值