事件和进程间的数据交换 . 分类: VC++ 2013-10-09 11:47 585人阅读 评论(0) 收藏
2013-10-09 11:47
501 查看
//========================================================================
//TITLE:
// 事件和进程间的数据交换
//AUTHOR:
// norains
//DATE:
// Monday 13-July-2009
//Environment:
// WINCE5.0 + VS2005
//========================================================================
多线程的数据交流不难,毕竟是同属于一个进程,更为重要的是,代码还很可能同属于一个工程,基本上想怎么干就怎么干,大不了我用一个全局变量来做缓存来进行数据的交换。
但对于多进程来说,就没那么容易了。从代码的角度来说,多进程意味不同的工程,意味着不能简单通过全局变量来交流数据。试想一下,如果IE有一个全局变量g_iCurPage,你用什么方法才能得到该数据?因此,在多进程的情况下,多线程那一套就没辙了。
不过,如果只是交流数据,情况倒不显得那么糟糕。一般的流程无非就是:假设有两个,分别是进程A和进程B,当线程A改变某些数值时,它会通过发送相应的事件给进程B;进程B在获得该通知事件后,会采取一定的方式,读取进程A所改变的数值。
听起来是不是很简单?
在讨论这个问题之前,我们先假设这两个进程存在如下架构的代码。
[cpp]
view plaincopyprint?
进程A:
DWORD NotifyProc(LPVOID pParam)
{
while(TRUE)
{
if(IsDataChange() != FALSE)
{
//TODO:准备好传送的数据
PulseEvent(hEventNotify);
}
}
}
进程B:
DWORD WaitNotifyProc(LPVOID pParam)
{
while(TRUE)
{
DWORD dwReturn = WaitForSingleObject(hEventNotify);
if(dwReturn != WAIT_TIMEOUT)
{
//TODO:获取相应的数据
}
}
}
该方法灵活性非常高,进程A如果想增加更多的通知数据,只需要简单地多设注册表项。而进程B可以不用管进程A设置了多少注册表项,只需要获取自己所需要的项目即可。
另外一个更为明显的优势在于,由于该方法是将数据保存于注册表,所以在进程B的运行是在进程A退出之后,进程B还能获取数据。甚至于,机器重启后,进程B依然能获取相应数据——前提条件是系统的注册表为Hive Registry。
如果说缺陷,确切地说是相对于另外两种方法而言,便是速度。因为期间会对注册表进行读写,所以速度会略有损失。如果对速度非常在意,那么该方法并不是最理想的。
2).内存印射
其实这种方式在我blog的另一篇文章《进程间的数据共享》(http://blog.csdn.net/norains/archive/2008/07/16/2663390.aspx)有提过,但为了本篇的完整性,在这里根据我们的论述框架重新来讨论一次。
原理很简单,进程A先调用CreateFileMapping开辟一个印射的内存区,然后往里面拷贝数据,最后通知进程B读取数据;进程B接受通知时,就直接调用memcpy从内存中获取数据。
[cpp]
view plaincopyprint?
进程A:
DWORD NotifyProc(LPVOID pParam)
{
//创建内存文件印射
HANDLE hFile = CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,MEM_SIZE,MEM_SHARE_NAME);
VOID * pMem = NULL;
if(hFile != NULL)
{
pMem = MapViewOfFile(hFile,FILE_MAP_ALL_ACCESS,0,0,0);
}
while(TRUE)
{
if(IsDataChange() != FALSE)
{
//拷贝传输的数据
if(pMem != NULL)
{
memcpy(pMem,&dwValue,sizeof(dwValue));
}
PulseEvent(hEventNotify);
}
}
//如果不再使用,应该关闭句柄
CloseHandle(hFile);
}
进程B:
DWORD WaitNotifyProc(LPVOID pParam)
{
//创建内存文件印射
HANDLE hFile = CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,MEM_SIZE,MEM_SHARE_NAME);
VOID * pMem = NULL;
if(hFile != NULL)
{
pMem = MapViewOfFile(hFile,FILE_MAP_ALL_ACCESS,0,0,0);
}
while(TRUE)
{
DWORD dwReturn = WaitForSingleObject(hEventNotify);
if(dwReturn != WAIT_TIMEOUT)
{
//拷贝传输过来的数据
if(pMem != NULL)
{
memcpy(&dwValue,pMem,sizeof(dwValue));
}
}
}
//如果不再使用,应该关闭句柄
CloseHandle(hFile);
}
该方式是最简单的,在传递DWORD长度类型的数据有得天独厚的优势,无论是速度还是简便性。但,也仅限于此,如果想采用该方式传递大小大于DWORD的数值,基本上会丢失精度,更不用说struct等结构体数值了。不过,这却是这三种方法之中,和事件联系最为紧密的。
//TITLE:
// 事件和进程间的数据交换
//AUTHOR:
// norains
//DATE:
// Monday 13-July-2009
//Environment:
// WINCE5.0 + VS2005
//========================================================================
多线程的数据交流不难,毕竟是同属于一个进程,更为重要的是,代码还很可能同属于一个工程,基本上想怎么干就怎么干,大不了我用一个全局变量来做缓存来进行数据的交换。
但对于多进程来说,就没那么容易了。从代码的角度来说,多进程意味不同的工程,意味着不能简单通过全局变量来交流数据。试想一下,如果IE有一个全局变量g_iCurPage,你用什么方法才能得到该数据?因此,在多进程的情况下,多线程那一套就没辙了。
不过,如果只是交流数据,情况倒不显得那么糟糕。一般的流程无非就是:假设有两个,分别是进程A和进程B,当线程A改变某些数值时,它会通过发送相应的事件给进程B;进程B在获得该通知事件后,会采取一定的方式,读取进程A所改变的数值。
听起来是不是很简单?
在讨论这个问题之前,我们先假设这两个进程存在如下架构的代码。
[cpp]
view plaincopyprint?
进程A:
DWORD NotifyProc(LPVOID pParam)
{
while(TRUE)
{
if(IsDataChange() != FALSE)
{
//TODO:准备好传送的数据
PulseEvent(hEventNotify);
}
}
}
进程B:
DWORD WaitNotifyProc(LPVOID pParam)
{
while(TRUE)
{
DWORD dwReturn = WaitForSingleObject(hEventNotify);
if(dwReturn != WAIT_TIMEOUT)
{
//TODO:获取相应的数据
}
}
}
[cpp] view plaincopyprint? 进程A: DWORD NotifyProc(LPVOID pParam) { while(TRUE) { if(IsDataChange() != FALSE) { //更改相应的注册表数值 CReg reg; reg.Create(HKEY_CURRENT_USER,DEVICE_INFO); reg.SetDW(MAIN_VOLUME,dwVal); reg.Close(); //发送通知事件 PulseEvent(hEventNotify); } } } 进程B: DWORD WaitNotifyProc(LPVOID pParam) { while(TRUE) { //等待通知事件 DWORD dwReturn = WaitForSingleObject(hEventNotify); if(dwReturn != WAIT_TIMEOUT) { //读取注册表 CReg reg; reg.Create(HKEY_CURRENT_USER,DEVICE_INFO); DWORD dwVal = 0; dwVal = reg.GetDW(MAIN_VOLUME); } } } 进程A: DWORD NotifyProc(LPVOID pParam) { while(TRUE) { if(IsDataChange() != FALSE) { //更改相应的注册表数值 CReg reg; reg.Create(HKEY_CURRENT_USER,DEVICE_INFO); reg.SetDW(MAIN_VOLUME,dwVal); reg.Close(); //发送通知事件 PulseEvent(hEventNotify); } } } 进程B: DWORD WaitNotifyProc(LPVOID pParam) { while(TRUE) { //等待通知事件 DWORD dwReturn = WaitForSingleObject(hEventNotify); if(dwReturn != WAIT_TIMEOUT) { //读取注册表 CReg reg; reg.Create(HKEY_CURRENT_USER,DEVICE_INFO); DWORD dwVal = 0; dwVal = reg.GetDW(MAIN_VOLUME); } } }
该方法灵活性非常高,进程A如果想增加更多的通知数据,只需要简单地多设注册表项。而进程B可以不用管进程A设置了多少注册表项,只需要获取自己所需要的项目即可。
另外一个更为明显的优势在于,由于该方法是将数据保存于注册表,所以在进程B的运行是在进程A退出之后,进程B还能获取数据。甚至于,机器重启后,进程B依然能获取相应数据——前提条件是系统的注册表为Hive Registry。
如果说缺陷,确切地说是相对于另外两种方法而言,便是速度。因为期间会对注册表进行读写,所以速度会略有损失。如果对速度非常在意,那么该方法并不是最理想的。
2).内存印射
其实这种方式在我blog的另一篇文章《进程间的数据共享》(http://blog.csdn.net/norains/archive/2008/07/16/2663390.aspx)有提过,但为了本篇的完整性,在这里根据我们的论述框架重新来讨论一次。
原理很简单,进程A先调用CreateFileMapping开辟一个印射的内存区,然后往里面拷贝数据,最后通知进程B读取数据;进程B接受通知时,就直接调用memcpy从内存中获取数据。
[cpp]
view plaincopyprint?
进程A:
DWORD NotifyProc(LPVOID pParam)
{
//创建内存文件印射
HANDLE hFile = CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,MEM_SIZE,MEM_SHARE_NAME);
VOID * pMem = NULL;
if(hFile != NULL)
{
pMem = MapViewOfFile(hFile,FILE_MAP_ALL_ACCESS,0,0,0);
}
while(TRUE)
{
if(IsDataChange() != FALSE)
{
//拷贝传输的数据
if(pMem != NULL)
{
memcpy(pMem,&dwValue,sizeof(dwValue));
}
PulseEvent(hEventNotify);
}
}
//如果不再使用,应该关闭句柄
CloseHandle(hFile);
}
进程B:
DWORD WaitNotifyProc(LPVOID pParam)
{
//创建内存文件印射
HANDLE hFile = CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,MEM_SIZE,MEM_SHARE_NAME);
VOID * pMem = NULL;
if(hFile != NULL)
{
pMem = MapViewOfFile(hFile,FILE_MAP_ALL_ACCESS,0,0,0);
}
while(TRUE)
{
DWORD dwReturn = WaitForSingleObject(hEventNotify);
if(dwReturn != WAIT_TIMEOUT)
{
//拷贝传输过来的数据
if(pMem != NULL)
{
memcpy(&dwValue,pMem,sizeof(dwValue));
}
}
}
//如果不再使用,应该关闭句柄
CloseHandle(hFile);
}
[cpp] view plaincopyprint? 进程A: DWORD NotifyProc(LPVOID pParam) { while(TRUE) { if(IsDataChange() != FALSE) { //设置关联数据 SetEventData(hEventNotify,dwData); PulseEvent(hEventNotify); } } } 进程B: DWORD WaitNotifyProc(LPVOID pParam) { while(TRUE) { DWORD dwReturn = WaitForSingleObject(hEventNotify); if(dwReturn != WAIT_TIMEOUT) { //获取关联数据 dwData = GetEventData(hEventNotify); } } } 进程A: DWORD NotifyProc(LPVOID pParam) { while(TRUE) { if(IsDataChange() != FALSE) { //设置关联数据 SetEventData(hEventNotify,dwData); PulseEvent(hEventNotify); } } } 进程B: DWORD WaitNotifyProc(LPVOID pParam) { while(TRUE) { DWORD dwReturn = WaitForSingleObject(hEventNotify); if(dwReturn != WAIT_TIMEOUT) { //获取关联数据 dwData = GetEventData(hEventNotify); } } }
该方式是最简单的,在传递DWORD长度类型的数据有得天独厚的优势,无论是速度还是简便性。但,也仅限于此,如果想采用该方式传递大小大于DWORD的数值,基本上会丢失精度,更不用说struct等结构体数值了。不过,这却是这三种方法之中,和事件联系最为紧密的。
相关文章推荐
- 进程中调用CreateMutex 分类: VC++ 2013-10-09 09:13 599人阅读 评论(0) 收藏
- 事件CEvent的使用 . 分类: VC++ 2013-11-02 14:31 499人阅读 评论(0) 收藏
- 服务级后门自己做——创建服务 分类: VC++ 2013-10-08 08:32 585人阅读 评论(0) 收藏
- 第3章 PCI总线的数据交换 分类: 浅谈PCI 2013-07-22 16:27 294人阅读 评论(0) 收藏
- 线程中CreateEvent和SetEvent及WaitForSingleObject的用法 分类: VC++ 2013-10-09 09:00 707人阅读 评论(0) 收藏
- udp协议的数据接收与发送的代码 分类: VC++ 网络基础 2014-02-25 08:15 700人阅读 评论(0) 收藏
- 四种进程或线程同步互斥的控制方法 分类: VC++ 2013-09-29 08:48 507人阅读 评论(0) 收藏
- 讨论MMU 分类: VC++ 2013-10-09 09:16 540人阅读 评论(0) 收藏
- windows进程间通信 . 分类: VC++ 2013-10-09 16:27 567人阅读 评论(0) 收藏
- FAT32文件系统的存储组织结构(一) 分类: VC++ 2014-08-27 08:40 504人阅读 评论(0) 收藏
- Retinex系列之McCann99 Retinex 分类: 图像处理 Matlab 2014-12-03 11:27 585人阅读 评论(0) 收藏
- 线程同步(信号量,互斥,条件变量) 分类: linux应用程序 2008-04-08 09:43 2587人阅读 评论(1) 收藏 举报 进行多线程编程,最头疼的就是那些共享的数据。因为你无法知道哪个线程会在哪个时候对它进行操作,你也无法
- Cocos2d-x事件分发机制学习笔记 分类: cocos2d代码编写 2015-07-27 18:02 6人阅读 评论(0) 收藏
- 你的变量究竟存储在什么地方 && 全局内存 分类: VC++ 2014-06-20 10:36 375人阅读 评论(0) 收藏
- PHP从零单排(十四)数据分页显示的原理及实现 分类: PHP 2014-05-01 22:05 325人阅读 评论(0) 收藏
- 处理Android SQLite -&n… 分类: Android数据存储 2014-05-30 10:58 95人阅读 评论(0) 收藏
- Linux查看进程的内存占用情况 分类: ubuntu 测试 2013-12-20 12:37 369人阅读 评论(0) 收藏
- 【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 管道 分类: Linux --- 应用程序设计 2014-11-05 11:18 75人阅读 评论(0) 收藏
- PPM图像格式(Portable Pixelmap) 分类: VC++ 文件格式 2014-11-25 11:32 513人阅读 评论(0) 收藏
- 利用Windows性能计数器(PerformanceCounter)监控 分类: windows驱动程序WDM VC++ 2015-03-10 10:44 369人阅读 评论(0) 收藏