最近公司重构代码,看到了公司的一位经验丰富的工程师的一些C++ 操作 属实有被秀到,估计光看他写的代码都够我写很多总结了。 根据他写的代码以及公司未来的代码的一些规划 我也总结一些无关痛痒的知识吧。
我们的新一代的代码架构将会去做到能实时的更换模块(就是c 编译出来的动态库 能动态的去加载! 目前的思路就是使用dlopen 以及dlclose的操作去动态的加载库文件) 之前一直没想到动态库的加载还可以这么的简单,高效。

下面的一些内容从大佬们的博客直接拼凑过来的  既然别人已经总结了一次 我就不去班门弄斧了
————————————————
版权声明:本文为CSDN博主「cybertan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cybertan/article/details/4383486

0 dlopen 相关的API

DLOPEN(3)          Linux Programmer's Manual               DLOPEN(3)#include <dlfcn.h>void *dlopen(const char *filename, int flag);char *dlerror(void);void *dlsym(void *handle, const char *symbol);int dlclose(void *handle);Link with -ldl.

0.1 dlopen()

该函数用来按照指定模式打开指定的共享库,将其影射到内存中,并且返回句柄。
第一个参数:指定共享库的名称,将会在下面位置查找指定的共享库。
-环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。
-文件/etc/ld.so.cache中找到的库的列表,用ldconfig维护。
-目录usr/lib。
-目录/lib。
-当前目录。
第二个参数:指定如何打开共享库。
-RTLD_NOW:将共享库中的所有函数加载到内存
-RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数

0.2 dlsym()

void *dlsym(void *restrict handle, const char *restrict name);

该函数返回一个指向由name所确定的请求入口点的指针。调用dlsym时,利用dlopen()返回的共享库的phandle以及函数/变量名称作为参数,返回要加载函数/变量的入口地址。

0.3 dlerror()

dlerror 返回 NULL 或者一个指向描述最近错误的 ASCII 字符串的指针

0.4 dlclose()

关闭句柄并且取消共享目标文件的映射

1. 一个简单的demo

//   main.cpp
#include <stdio.h>
#include <dlfcn.h>
int main(void)
{int abc = 123;printf("[%s] #line %d exec ...\n",__FUNCTION__,__LINE__);void *p = dlopen("./libmodule1.so",RTLD_LAZY);printf("[%s] #line %d p = %p\n",__FUNCTION__,__LINE__,p);printf("[%s] #line %d exec ...\n",__FUNCTION__,__LINE__);void* sym = dlsym(p,"temp1");printf("[%s] #line %d sym[temp1] = %p\n",__FUNCTION__,__LINE__,sym);printf("[%s] #line %d exec ...\n",__FUNCTION__,__LINE__);printf("[%s] #line %d exec ...\n",__FUNCTION__,__LINE__);return 0;
}
// module1.cpp
#include <stdio.h>
class temp{public:temp() {printf("[%s] #line %d exec ...\n",__FUNCTION__,__LINE__);printf("[%s] #line %d this = %p  ...\n",__FUNCTION__,__LINE__,this);}
} temp1;
cmake_minimum_required(VERSION 3.16)
project(dlopenTest)add_executable(appmain.cpp)
target_link_libraries(app dl
)
add_library(module1 SHAREDmodule1.cpp
)
[jeason@centos7 dlopen]$ ls
CMakeLists.txt  main.cpp  module1.cpp
[jeason@centos7 dlopen]$ mkdir build && cd build
[jeason@centos7 build]$ cmake ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jeason/dlopen/build
[jeason@centos7 build]$ make
[ 25%] Building CXX object CMakeFiles/app.dir/main.cpp.o
[ 50%] Linking CXX executable app
[ 50%] Built target app
[ 75%] Building CXX object CMakeFiles/module1.dir/module1.cpp.o
[100%] Linking CXX shared library libmodule1.so
[100%] Built target module1
[jeason@centos7 build]$ ./app
[main] #line 7 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7f6091f79039  ...
[main] #line 10 p = 0x1bb2030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f6091f79039
[main] #line 15 exec ...
[main] #line 17 exec ...
[jeason@centos7 build]$

上面的例子里面 在动态库里面我创建了一个 类,然后就调用了类的构造函数,然后 这个函数就打印出来了
this = 0x7f6091f79039 这个地址和我后面使用 dlsym 函数获得的指针是一个地址,也就是说我可以用dlsym 拿到这个指针。

1.1 简单修改

简单修改一下代码 测试一下 dlclose 的一些特性

[jeason@centos7 build]$ make && ./app
Consolidate compiler generated dependencies of target app
[ 50%] Built target app
[ 75%] Building CXX object CMakeFiles/module1.dir/module1.cpp.o
[100%] Linking CXX shared library libmodule1.so
[100%] Built target module1
[main] #line 8 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7ff5f34b5041  ...
[main] #line 11 p = 0x15a6030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7ff5f34b5041
[~temp] #line 9 exec ...
[main] #line 18 exec ...
[main] #line 20 exec ...
[jeason@centos7 build]$
[jeason@centos7 build]$

我们可以明显的看到 temp 的构造和析构一直在被调用。
接下来屏蔽 dlclose 看一下效果

[jeason@centos7 build]$
[jeason@centos7 build]$ make && ./app
[ 25%] Building CXX object CMakeFiles/app.dir/main.cpp.o
[ 50%] Linking CXX executable app
[ 50%] Built target app
Consolidate compiler generated dependencies of target module1
[100%] Built target module1
[main] #line 8 exec ...
[temp] #line 5 exec ...
[temp] #line 6 this = 0x7f4435433041  ...
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 11 p = 0x1a0e030
[main] #line 12 exec ...
[main] #line 14 sym[temp1] = 0x7f4435433041
[main] #line 18 exec ...
[main] #line 20 exec ...
[~temp] #line 9 exec ...
[jeason@centos7 build]$

我们可以发现 这个类只是被构造了一次! 只是在程序退出的时候析构了一次,而且 我们还可以直接通过dlopen 拿到相同的一个指针

后面的需求实现就是看 程序猿自己去发挥了 要想实现 我们新版本的代码框架中动态的加载和卸载一些模块

嵌入式linux学习笔记-- 对于动态库的一些操作 dlopen相关推荐

  1. Linux学习笔记-生成动态库(补充说明)

    1.在Makefile中创建动态库. 2.在动态库中共享class类型. Makefile文件如下: EXE=libexample.so SUBDIR=srcCXX_SOURCES=$(foreach ...

  2. 嵌入式linux学习笔记--TCP通讯整理

    嵌入式linux学习笔记–TCP通讯整理 之前的项目中使用到了比较多的tcp 通讯相关的知识,一直也没有进行整理,今天准备拿出时间好好的整理一下TCP通讯的整个过程.预计会整理linux和window ...

  3. 迅为嵌入式Linux学习笔记4——进程

    迅为嵌入式Linux学习笔记4--进程 进程指的是正在运行的程序,是操作系统分配资源的最小单位. 进程ID 每个进程都有唯一的标识符,这个标识符就是进程ID,简称pid 进程间通信的方法 管道通信:分 ...

  4. 迅为嵌入式Linux学习笔记5——进程间通信

    迅为嵌入式Linux学习笔记5--进程间通信 管道通信 无名管道 无名管道只能实现有亲缘关系的进程之间的通信,比如父子进程. pipe函数: #include <unistd.h> int ...

  5. 嵌入式Linux学习笔记—fastboot烧写Android

    本系列为本人在自学过程中的学习笔记,如有错误欢迎大家指正. 学习资料为讯为ITOP4412开发板. fastboot烧写Android 1.主要工具 OTG 接口烧写方式也叫 fastboot 烧写方 ...

  6. 【linux学习笔记】嵌入式linux学习笔记

    目录: 1.SWAP 交换分区 2.GRUB  3.块设备和字符设备  4.shell 7.静态函数库\动态库 8.交叉编译 9.系统调用 10.文件 I/O编程 11.进程和线程 12.磁盘和文件系 ...

  7. 嵌入式linux编程,嵌入式Linux学习笔记 - 嵌入式Linux基础知识和开发环境的构建_Linux编程_Linux公社-Linux系统门户网站...

    注:所有内容基于友善之臂Mini2440开发板 一.嵌入式Linux开发环境的构建 嵌入式开发一般分为三个步骤: 1.编译bootloader,烧到开发板 2.编译嵌入式Linux内核,烧到开发板 3 ...

  8. linux内核编译选项ccl,嵌入式Linux学习笔记(一)

    注:所有内容基于友善之臂Mini2440开发板 一.嵌入式Linux开发环境的构建 嵌入式开发一般分为三个步骤: 1.编译bootloader,烧到开发板 2.编译嵌入式Linux内核,烧到开发板 3 ...

  9. 嵌入式linux学习笔记(一)

    最近开始学习linux驱动编写,目前直接使用jz2440已移植好的系统配合视频开始学习驱动编写,但是总是出现这样那样的问题.于是决定重头开始,先自己移植内核,在开始驱动学习. 今天参照<嵌入式l ...

最新文章

  1. [再寄小读者之数学篇](2014-04-18 from 352558840@qq.com [南开大学 2014 年高等代数考研试题]二次型的零点)...
  2. 梅尔频率倒谱系数(MFCC)资源
  3. golang reflect Pointer 获取 传入的interface信息
  4. hibernate数据类型_Hibernate类型初学者指南
  5. 精简SWT FormLayout的用法
  6. 获取iOS任意线程调用堆栈(五)完整实现:BSBacktraceLogger
  7. 计算机 项目管理 stage phase区别
  8. 熊猫烧香能破坏计算机硬件吗,熊猫烧香病毒会伤害电脑硬件吗?
  9. 电脑常用良心软件推荐!!!
  10. 统计学中p值计算公式_统计学中的P值应该怎么计算
  11. 两个excel宏病毒
  12. 7年阿里Java人教你:秒杀活动就应该这样玩?
  13. 用户名xxx不在sudoers文件中,此事将被报告
  14. 基于博客系统的访客日志记录
  15. Java核心编程(22)
  16. discuz论坛添加、更换返回顶部图标
  17. PC版微信内置浏览器 缓存文件保存位置
  18. video.js API 详解
  19. window的onload事件的用法
  20. 公园景区广播系统方案

热门文章

  1. 一款超级简单的后台管理系统模板
  2. Python将dat文件转化csv文件
  3. StarUML——一款在MAC上的UML软件
  4. Flume 尚硅谷2019
  5. 飞鸽传书、freeeim、ipmsg区别联系
  6. 思科在中国已建成355所网络技术学院
  7. 大数据标准管理体系流程
  8. 计算机整个文稿应用回顾主题,计算机应用教案16.doc
  9. Kettle的一些常见问题
  10. 大数据领域三个大的技术方向资料