动态链接--运行时加载dlopen
前面我们在编译可执行文件时,如果可执行文件要依赖某个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的更多相关文章
- Linux下显示运行时链接(运行时加载)
目录 介绍 如何加载动态库 dlopen() 第一个参数: 被加载动态库的路径 第二个参数: flag表示函数符号的解析方式 dlopen 返回值 dlsym() 参数: 返回值 符号优先级 dler ...
- Windows 运行时加载动态库
下面是一个运行时加载nvcuda.dll,并检测当前驱动版本最大支持的CUDA版本的例子. #include "cuda.h" #include <stdio.h> # ...
- QT运行时加载UI文件
写QT程序里运行时加载UI文件,代码如下: 点击(此处)折叠或打开 #include "keyboard.h" #include <QtUiTools> #incl ...
- commonJs的运行时加载和es6的编译时加载
参考 : https://www.cnblogs.com/jerrypig/p/8145206.html 1.commonJs的运行时加载 2.ES6编译时加载
- linux 运行时加载不上动态库 解决方法(转)
1. 连接和运行时库文件搜索路径到设置 库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的.一般 Linux 系统把 /lib 和 /usr ...
- Spark on Yarn运行时加载的jar包
spark on yarn运行时会加载的jar包有如下: spark-submit中指定的--jars $SPARK_HOME/jars下的jar包 yarn提供的jar包 spark-submit通 ...
- Java源文件编译成功但是运行时加载不到文件
最近系统重装了一些,Java等环境变量都需要重新配置,配置好以后编写了一个Java源文件编译了一下,通过Javac编译源文件,编译成功,但是再通过Java运行时没找到报出找不到加载文件或者加载文件不存 ...
- spark运行时加载配置文件(hive,hdfs)
文章为转载,如有版权问题,请联系,谢谢! 转自:https://blog.csdn.net/piduzi/article/details/81636253 适合场景:在运行时才确定用哪个数据源 imp ...
- 【转】Sqlite 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该...
开发环境: vs2010+.net framework 4.0+ System.Data.SQLite.DLL (2.0)今天在做Sqlite数据库测试,一运行程序在一处方法调用时报出了一个异常 混合 ...
随机推荐
- PP: GRU-ODE-Bayes: Continuous modeling of sporadically-observed time series
From: KU Leuven; ESAT-STADIUS比利时鲁汶大学 ?? How to model real-world multidimensional time series? especi ...
- Linux - pip 安装使用说明
简介 pip类似RedHat里面的yum,安装Python包非常方便.本节详细介绍pip的安装.以及使用方法 方案一 wget https://bootstrap.pypa.io/get-pip.py ...
- 重载(Overload)和重写(Override)的区别是什么?
首先java程序的运行分为编译和运行两部分. 所以重载和重写在这一点就有很明显的区别,因为重写方法的方法名和参数个数类型都一样,所以在java虚拟机的编译阶段是识别不出重写的方法的不同,在运行期间才可 ...
- 《 Java 编程思想》CH07 复用类
复用代码是 Java 众多引人注目的功能之一. Java 可以通过创建类来复用代码,要在使用类的时候不破坏现有代码,有两种方式: 组合:在新的类中使用现有类的对象. 继承:按照现有类的类型来创建新类, ...
- 3ds Max File Format (Part 5: How it all links together; ReferenceMaker, INode)
At this point, you should start to familiarize yourself a bit with the publicly available 3ds Max AP ...
- Centsos7 aria2
wget -N --no-check-certificate https://raw.githubusercontent.com/ToyoDAdoubi/doubi/master/aria2.sh & ...
- ORA-01935: missing user or role name
问题描述 ORA-01935: missing user or role name ORA-01935:缺少用户或角色名
- 微信小程序前台的用户数据入库(后台Laravel)
首先 我们可以看到微信小程序官方 文档 wx.login api-login.jpg 通过此图 我们知道 前台要传 一个 code给后台,后台拿到code 并结合appid和appsecret请求 ...
- 【算法学习记录-排序题】【PAT A1016】Phone Bills
A long-distance telephone company charges its customers by the following rules: Making a long-distan ...
- 环境配置 | Pycharm远程开发的环境配置
目的:同局域网中的两台电脑,Mac上看视频学习编程 + 当服务器跑代码:Windows上使用Pycharm写代码.学习远程开发 (当前底子有限,很多操作可能存在理解偏差) Mac上代码存放路径:~/O ...