前面我们在编译可执行文件时,如果可执行文件要依赖某个so。必须要通过-L指定so路径,并且-l指定so名字。

而且在可执行文件运行时,要先加载so的load部分到进程地址空间。

有一种方式可以在编译时不需要link so, 而且程序运行过程中去加载so。

dlopen函数可以在进程运行过程中,打开so,将其加载到进程的地址空间,并完成初始化过程。

如果dlopen中指定的路径是相对路径,那么按照LD_LIBRARY_PATH,/etc/ld.so.cache,/lib,/usr/lib顺序查找。否则直接打开so。

dlsym返回so的符号的值,如果符号是函数和变量,返回符号和变量的地址;如果符号是常量,就返回常量的值。

我们在前面写的消息队列msgsnd.c代码中稍作修改,以运行时加载libmsg.so。代码如下:

#include <sys/prctl.h>

#include <string.h>
#include <stdio.h>
#include <dlfcn.h>
#include "msg.h"
#define MSG_CREAT_PATH "/mnt/hgfs/share/test/list"
#define MSG_RCV_ID 4
#define MSG_SND_ID 3
typedef int (*create_msg_queue)(const char *path, int proj_id);
typedef int (*rcv_msg)(int id, FellowMsg *msg);
typedef int (*snd_msg)(int id, FellowMsg *msg);
typedef struct _MsgIf{
  create_msg_queue create;
  rcv_msg rcv;
  snd_msg snd;
}MsgIf;
MsgIf msgIf;
void *fellow_listenning_msg(void *arg)
{
  if(0 != prctl(PR_SET_NAME, (unsigned long)"fellow_process_msg"))
  {
    printf("prctl fail, errno:%d", errno);
  }
  int msg_q_id = msgIf.create(MSG_CREAT_PATH, MSG_RCV_ID);
  FellowMsg _fellowMsg;
  while (1)
  {
    memset(&_fellowMsg, 0, sizeof(FellowMsg));
    msgIf.rcv(msg_q_id, &_fellowMsg);
    if (CTRL_FEEDBACK ==_fellowMsg._msgType)
    {
      switch (_fellowMsg._ctlInfo.u._ctlFeedback)
      {
        case OPEN_DONE:
        printf("rcv OPEN_DONE:%d\n", _fellowMsg._ctlInfo.param);
        break;
        case CLOSE:
        printf("rcv CLOSE_DONE:%d\n", _fellowMsg._ctlInfo.param);
        break;
        case PLAY:
        printf("rcv PLAY_DONE:%d\n", _fellowMsg._ctlInfo.param);
        break;
        default:
        break;

      }
    }

  }
}
void main(void)
{
  void *handle = dlopen("/mnt/hgfs/share/test/msg/libmsg.so", RTLD_NOW);//打开libmsg.so
  if (NULL == handle)
  {
    printf("dlopen fail:%s\n", dlerror());
    return;
  }
  msgIf.create = (create_msg_queue)dlsym(handle, "fellow_create_msg_queue");//获取符号的值。
  msgIf.rcv = (rcv_msg)dlsym(handle, "fellow_rcv_msg");
  msgIf.snd = (snd_msg)dlsym(handle, "fellow_send_msg");
  pthread_t thread_id;
  int snd_msg_q_id = msgIf.create(MSG_CREAT_PATH, MSG_SND_ID);
  printf("msgid:%d\n",snd_msg_q_id);
  FellowMsg _fellowMsg;
  _fellowMsg._msgType = CTRL_CMD;
  _fellowMsg._ctlInfo.u._ctlCmd = OPEN;
  _fellowMsg._ctlInfo.param = 1;
  printf("create:%p, snd:%p, rcv:%p\n", msgIf.create, msgIf.snd,msgIf.rcv);
  msgIf.snd(snd_msg_q_id, &_fellowMsg);
  pthread_create(&thread_id, NULL, fellow_listenning_msg, NULL);
  while (1)
  {
  }
  dlclose(handle);
}

那么在编译时我们不需要link so: gcc msgsnd.c -o msgsnd -ldl -pthread

动态链接--运行时加载dlopen的更多相关文章

  1. Linux下显示运行时链接(运行时加载)

    目录 介绍 如何加载动态库 dlopen() 第一个参数: 被加载动态库的路径 第二个参数: flag表示函数符号的解析方式 dlopen 返回值 dlsym() 参数: 返回值 符号优先级 dler ...

  2. Windows 运行时加载动态库

    下面是一个运行时加载nvcuda.dll,并检测当前驱动版本最大支持的CUDA版本的例子. #include "cuda.h" #include <stdio.h> # ...

  3. QT运行时加载UI文件

      写QT程序里运行时加载UI文件,代码如下: 点击(此处)折叠或打开 #include "keyboard.h" #include <QtUiTools> #incl ...

  4. commonJs的运行时加载和es6的编译时加载

    参考 : https://www.cnblogs.com/jerrypig/p/8145206.html 1.commonJs的运行时加载 2.ES6编译时加载

  5. linux 运行时加载不上动态库 解决方法(转)

    1. 连接和运行时库文件搜索路径到设置     库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的.一般 Linux 系统把 /lib 和 /usr ...

  6. Spark on Yarn运行时加载的jar包

    spark on yarn运行时会加载的jar包有如下: spark-submit中指定的--jars $SPARK_HOME/jars下的jar包 yarn提供的jar包 spark-submit通 ...

  7. Java源文件编译成功但是运行时加载不到文件

    最近系统重装了一些,Java等环境变量都需要重新配置,配置好以后编写了一个Java源文件编译了一下,通过Javac编译源文件,编译成功,但是再通过Java运行时没找到报出找不到加载文件或者加载文件不存 ...

  8. spark运行时加载配置文件(hive,hdfs)

    文章为转载,如有版权问题,请联系,谢谢! 转自:https://blog.csdn.net/piduzi/article/details/81636253 适合场景:在运行时才确定用哪个数据源 imp ...

  9. 【转】Sqlite 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该...

    开发环境: vs2010+.net framework 4.0+ System.Data.SQLite.DLL (2.0)今天在做Sqlite数据库测试,一运行程序在一处方法调用时报出了一个异常 混合 ...

随机推荐

  1. ubantu安装apache

    1.命令安装: sudo apt install apache2 2.检查是否启动了Apache服务 systemctl status apache2 3.开启.关闭和重启服务器 /etc/init. ...

  2. window.resizeTo

    概述 动态调整窗口的大小. 语法 window.resizeTo(aWidth, aHeight) 参数 aWidth 是一个整数,表示新的 outerWidth(单位:像素)(包括滚动条.窗口边框等 ...

  3. gz、tar、zip、bz2压缩和解压缩命令

    gzip 压缩后的格式为:*.gz 这种压缩方式不能保存原文件:且不能压缩目录 命令举例:#压缩[root@localhost tmp]# gzip buodo[root@localhost tmp] ...

  4. jQuery---jQuery初体验

    jQuery初体验 1. 引入jquery文件 2. 入口函数标准 jQuery优点总结 (对应的就是js的缺点): 查找元素的方法多种多样,非常灵活 拥有隐式迭代特性,因此不需要手写for循环 完全 ...

  5. 一文带你看清HTTP所有概念(转)

    一文带你看清HTTP所有概念   上一篇文章我们大致讲解了一下 HTTP 的基本特征和使用,大家反响很不错,那么本篇文章我们就来深究一下 HTTP 的特性.我们接着上篇文章没有说完的 HTTP 标头继 ...

  6. yii消息提示扩展

    //安装 composer.phar require --prefer-dist yiister/yii2-gentelella "~1.0" //消息存入 Yii::$app-& ...

  7. 《深入理解Java虚拟机》读书笔记九

    第十章 早期(编译期)优化 1.Javac的源码与调试 编译期的分类: 前端编译期:把*.java文件转换为*.class文件的过程.例如sun的javac.eclipseJDT中的增量编译器. JI ...

  8. Linux MYSQL安装指南

    安装环境:系统是 centos6.5 1.下载 下载地址:http://dev.mysql.com/downloads/mysql/5.6.html#downloads 下载版本:我这里选择的5.6. ...

  9. 基于Java在线学习系统设计与实现

                 Spring+SpringMVC+MyBatis+Bootstrap+Vue开发在线学习系统 本课题的主要内容是开发基于Java EE的在线学习平台,使用MVC经典开发模式. ...

  10. POJ3258 River Hopscotch(二分最大化最小值)

    题目链接:http://poj.org/problem?id=3258 题意:给n个石头,起点和终点也是两个石头,去掉这石头中的m个,使得石头间距的最小值最大. 思路:二分石头间的最短距离,每次贪心地 ...