WINCE下进程间通信(一)
WINCE下进程间通信(一)
在WINCE开发中经常需要在不同的进程之间传递、共享数据,总结了一下,WINCE下进程间通信常用的方式有:Windows消息,共享内存,socket通信,管道,全局原子,邮槽等,下面就分别对这几种方法做个小结。(当然还可以采用注册表,磁盘文件以及数据库方式,只是这几种方式的通信效率和实时性比较低,所以一般不考虑。)
一、Windows消息
通过Windows消息,可以很方便的在进程与进程之间传递数据。对于传递像字符串这种小的数据,可以直接将字符串以消息参数wParam、lParam的方式传递给其他进程,对于大一点的数据,可以采用发送WM_COPYDATA消息,参考代码如下:
- void SendMsg(HWND hwnd,LPVOID lpData,DWORD dwSize)
- {
- // 填充COPYDATASTRUCT结构
- COPYDATASTRUCT cpd;
- cpd.cbData = dwSize;
- cpd.lpData = lpData;
- // 向指定窗口发送WM_COPYDATA消息,不能用PostMessage方式发送
- ::SendMessage(hwnd, WM_COPYDATA, NULL,(LPARAM)&cpd);
- }
- // 发送端
- TCHAR *data=_T("要发送的内容");
- SendMsg(::FindWindow(NULL,_T("processB")),(void*)data,_tcslen(data)*2);
void SendMsg(HWND hwnd,LPVOID lpData,DWORD dwSize)
{
// 填充COPYDATASTRUCT结构
COPYDATASTRUCT cpd;
cpd.cbData = dwSize;
cpd.lpData = lpData;
// 向指定窗口发送WM_COPYDATA消息,不能用PostMessage方式发送
::SendMessage(hwnd, WM_COPYDATA, NULL,(LPARAM)&cpd);
}
// 发送端
TCHAR *data=_T("要发送的内容");
SendMsg(::FindWindow(NULL,_T("processB")),(void*)data,_tcslen(data)*2);
在接收端的窗口过程处理函数中添加对WM_COPYDATA消息的处理
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- PAINTSTRUCT ps;
- HDC hdc;
- TCHAR data[256]={0};
- switch (message)
- {
- case WM_COPYDATA:
- {
- COPYDATASTRUCT *pCopyDataStruct=(COPYDATASTRUCT *)lParam;
- memcpy(data,pCopyDataStruct->lpData,pCopyDataStruct->cbData);
- }
- break;
- // ...
- }
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR data[256]={0};
switch (message)
{
case WM_COPYDATA:
{
COPYDATASTRUCT *pCopyDataStruct=(COPYDATASTRUCT *)lParam;
memcpy(data,pCopyDataStruct->lpData,pCopyDataStruct->cbData);
}
break;
// ...
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
需要注意的是在发送数据量较大且数据交换频繁的时候通过发送WM_COPYDATA消息是不可取的,因为当数据传输过于频繁时将有可能导致数据的丢失。
二、共享内存
共享内存顾名思义是在内存中创建一个公共区域,供不同的进程间的数据共享。因为是直接对内存进行读写操作,效率非常高,所以共享内存特别适用于大批量的数据传输且实时性要求比较高的场合。
具体操作步骤如下:
1.进程A调用CreateFileMapping创建一个内存映射文件。
2.进程A调用MapViewOfFile获取到映射到文件的内存起始地址,调用memcpy往内存中拷贝数据。
3.进程B调用CreateFileMapping打开进程A创建的内存映射文件。
4.进程B调用MapViewOfFile获取到映射到文件的内存起始地址,调用memcpy从内存中读出数据。
5.通信完后进程A,B分别调用UnmapViewOfFile,CloseHandle取消内存映射和关闭内存映射对象句柄。
为了简化操作,这里封装了一个共享内存操作类,参考代码如下:
头文件CShareMemory.h:
- /*******************************************************************
- filename: CShareMemory.h
- purpose: 封装了共享内存操作类
- author: firehood
- created: 2011.03.16
- ********************************************************************/
- #ifndef _SHARE_MEMORY_H
- #define _SHARE_MEMORY_H
- class CShareMemory
- {
- public:
- CShareMemory();
- ~CShareMemory();
- public:
- /**********************************************************
- 函数名:Open
- 功能: 创建或打开内存映射文件
- 参数:
- [in]szMapName: 要创建的共享内存名称
- [in]dwSize: 创建共享内存的大小
- 返回值:
- 0: 失败
- 1: 创建成功
- 2: 文件已存在
- ***********************************************************/
- DWORD Open(LPCTSTR szMapName,DWORD dwSize);
- /**********************************************************
- 函数名:Read
- 功能: 从共享内存指定位置读取数据
- 参数:
- [out]pBuf: 存放读取的数据
- [in]dwSize: 读取数据的大小
- [in]dwOffset 距共享内存起始位置的偏移量
- 返回值:
- TRUE: 成功 FALSE:失败
- ***********************************************************/
- BOOL Read(void* pBuf,DWORD dwSize,DWORD dwOffset = 0);
- /**********************************************************
- 函数名:Write
- 功能: 从共享内存指定位置写入数据
- 参数:
- [in]pBuf: 待写入的数据指针
- [in]dwSize: 写入数据的大小
- [in]dwOffset 距共享内存起始位置的偏移量
- 返回值:
- TRUE: 失败 FALSE:失败
- ***********************************************************/
- BOOL Write(const void* pBuf,DWORD dwSize,DWORD dwOffset = 0);
- void Close(void);
- private:
- HANDLE m_hShareMemory;
- LPVOID m_pMapBuffer;
- HANDLE m_hAccessMutex;
- };
- #endif
/*******************************************************************
filename: CShareMemory.h
purpose: 封装了共享内存操作类
author: firehood
created: 2011.03.16
********************************************************************/
#ifndef _SHARE_MEMORY_H
#define _SHARE_MEMORY_H
class CShareMemory
{
public:
CShareMemory();
~CShareMemory();
public:
/**********************************************************
函数名:Open
功能: 创建或打开内存映射文件
参数:
[in]szMapName: 要创建的共享内存名称
[in]dwSize: 创建共享内存的大小
返回值:
0: 失败
1: 创建成功
2: 文件已存在
***********************************************************/
DWORD Open(LPCTSTR szMapName,DWORD dwSize);
/**********************************************************
函数名:Read
功能: 从共享内存指定位置读取数据
参数:
[out]pBuf: 存放读取的数据
[in]dwSize: 读取数据的大小
[in]dwOffset 距共享内存起始位置的偏移量
返回值:
TRUE: 成功 FALSE:失败
***********************************************************/
BOOL Read(void* pBuf,DWORD dwSize,DWORD dwOffset = 0);
/**********************************************************
函数名:Write
功能: 从共享内存指定位置写入数据
参数:
[in]pBuf: 待写入的数据指针
[in]dwSize: 写入数据的大小
[in]dwOffset 距共享内存起始位置的偏移量
返回值:
TRUE: 失败 FALSE:失败
***********************************************************/
BOOL Write(const void* pBuf,DWORD dwSize,DWORD dwOffset = 0);
void Close(void);
private:
HANDLE m_hShareMemory;
LPVOID m_pMapBuffer;
HANDLE m_hAccessMutex;
};
#endif
源文件CShareMemory.cpp:
- #include "stdafx.h"
- #include "CShareMemory.h"
- CShareMemory::CShareMemory()
- {
- m_hShareMemory = NULL;
- m_pMapBuffer = NULL;
- m_hAccessMutex =NULL;
- }
- CShareMemory::~CShareMemory()
- {
- Close();
- }
- DWORD CShareMemory::Open(LPCTSTR szMapName,DWORD dwSize)
- {
- DWORD dwRet = 1;
- if(szMapName == NULL)
- return 0;
- if(m_hShareMemory)
- {
- Close();
- }
- // 创建内存映射文件对象
- m_hShareMemory = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,dwSize,szMapName);
- if(!m_hShareMemory)
- {
- return 0;
- }
- // 内存映射文件对象已存在
- if(GetLastError() == ERROR_ALREADY_EXISTS)
- {
- dwRet = 2;
- }
- // 获取内存映射文件指针
- m_pMapBuffer = MapViewOfFile(m_hShareMemory,FILE_MAP_ALL_ACCESS,0,0,0);
- if(!m_pMapBuffer)
- {
- CloseHandle(m_hShareMemory);
- return 0;
- }
- // 创建互斥体,用于读写同步
- TCHAR szMutexName[MAX_PATH];
- _tcscpy(szMutexName, szMapName);
- _tcscat(szMutexName, _T("_Mutex"));
- m_hAccessMutex=CreateMutex(NULL, FALSE, szMutexName);
- if(!m_hAccessMutex)
- {
- Close();
- return 0;
- }
- return dwRet;
- }
- BOOL CShareMemory::Read(void* pBuf,DWORD dwSize,DWORD dwOffset)
- {
- BOOL bRet;
- if(!m_pMapBuffer) return FALSE;
- if(WaitForSingleObject(m_hAccessMutex,INFINITE)==WAIT_OBJECT_0)
- {
- memcpy(pBuf,(BYTE*)m_pMapBuffer+dwOffset,dwSize);
- bRet = TRUE;
- }
- ReleaseMutex(m_hAccessMutex);
- return bRet;
- }
- BOOL CShareMemory::Write(const void* pBuf,DWORD dwSize,DWORD dwOffset)
- {
- BOOL bRet;
- if(!m_pMapBuffer) return FALSE;
- if(WaitForSingleObject(m_hAccessMutex,INFINITE)==WAIT_OBJECT_0)
- {
- memcpy((BYTE*)m_pMapBuffer+dwOffset,pBuf,dwSize);
- bRet = TRUE;
- }
- ReleaseMutex(m_hAccessMutex);
- return TRUE;
- }
- void CShareMemory::Close(void)
- {
- if(m_hShareMemory)
- {
- UnmapViewOfFile(m_pMapBuffer);
- CloseHandle(m_hShareMemory);
- m_pMapBuffer = NULL;
- m_hShareMemory = NULL;
- }
- if(m_hAccessMutex)
- {
- CloseHandle(m_hAccessMutex);
- m_hAccessMutex = NULL;
- }
- }
WINCE下进程间通信(一)的更多相关文章
- WINCE下进程间通信(二)
WINCE下进程间通信(二) 接着前面的文章<WINCE下进程间通信(一)>,现在介绍进程间通信的另一种方法. 三.管道(消息队列) WINCE并不支持类似于PC机上匿名管道.命名管道的通 ...
- WinCE下读取注册表获得SD路径
WinCE下读取注册表获得SD路径 [要点]WinCE注册表中[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory\] 下键Folde ...
- WinCE下GPRS自动拨号软件(GPRS AutoDial)
之前在WinCE下调试USB的3G Modem时,写过一个拨号助手RASManager,基本能用.后来车机卖到俄罗斯去,客户老M提供了一个更好的GPRS自动拨号软件GPRS AutoDial,功能完善 ...
- Wince下sqlce数据库开发(二)
上次写到使用数据绑定的方法测试本地sqlce数据库,这次使用访问SQL Server的方法访问sqlce,你会发现他们是如此的相似... 参考资料:http://www.cnblogs.com/rai ...
- Wince下sqlce数据库开发(一)
对于Wince下的sqlce数据库虽然很多人在用,但在我查找资料时,却发现资料是多么的匮乏,在此对自己这几天的了解做个简单介绍,希望对大家能有所帮助! 本文的最后附有所使用到的sqlce在wince下 ...
- 浅析Linux下进程间通信:共享内存
浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...
- 在Window Embedded CE(Wince)下使用OpenNETCF进行路由表的开发
点击打开链接 背景 在开发3G项目的是时候,发现尽管3G网络连接已经建立成功了,但是数据不能发送成功,查明原因,由于路由表的问题,导致数据往ActiveSync连接的对端,也就是PC发送,而不是发送到 ...
- WinCE下使用C#获得带毫秒的DateTime.Now
在WinCE下,使用DateTime.Now获取的系统时间是不带毫秒的,如果想要它带毫秒,需要耍点手段.话不多说,直接上代码: public static DateTimePrecisely { // ...
- wince下sources\sources.cmn\Makefile.def的相关作用
1:首先是Makefile.def: ---------------------------------------- 在所有驱动的makefile中有!INCLUDE $(_MAKEENVROOT) ...
随机推荐
- iOS UIApplication 里面各const实际用意
//后台通知:屏幕操作通知等等 UIKIT_EXTERN NSString *const UIApplicationDidEnterBackgroundNotification NS_AV ...
- ContentPlaceHolderID属性
用来对应包含与当前内容关联的 ContentPlaceHolder 的 ID啊 说白了就是去找母版页相应的ContentPlaceHolder ,然后把内容扔进那里面去 <asp:Content ...
- ASP.NET MVC 使用TempData
ASP.NET MVC的TempData用于传输一些临时的数据,例如在各个控制器Action间传递临时的数据或者给View传递一些临时的数据,相信大家都看过"在ASP.NET页面间传值的方法 ...
- hud 2549 壮志难酬
Problem Description 话说MCA山上各路豪杰均出山抗敌,去年曾在江湖威名显赫的,江湖人称<万军中取上将首级舍我其谁>的甘露也不甘示弱,“天将降大任于斯人也,必先劳其筋骨, ...
- vs设计界面出现“建控件时出错 响应在此上下文中不可用”
使用VS2010设计Asp.net时出现: 只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态.还请确保在应用程序配置的 \\ 节中包括 ...
- ubuntu下 编译Caffe的Matlab接口
一般情况下不愿意使用Caffe的Matlab接口,总觉得Linux版的Matlab很难配置,但是现在搞目标检测,得到的源码是使用的Caffe的Matlab接口,只能硬着头皮上了. (1)修改caffe ...
- java数据结构之链表的实现
这个链表的内部是使用双向链表来表示的,但是并未在主函数中进行使用 /** * 链表 * 2016/4/26 **/ class LinkList{ Node head = new Node(); No ...
- pat L2-006. 树的遍历
L2-006. 树的遍历 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历 ...
- 转:Loadrunner——Block(块)技术
在使用LoadRunner时经常遇到这样一个问题,如果对不同的事务进行不同次数的循环该怎么处理?默认情况下LR对所有的事务都是统一执行的,即虽然有多个事务,但它们被执行的循环次数都是一样的,那么LR如 ...
- .Net多线程编程—Parallel LINQ、线程池
Parallel LINQ 1 System.Linq.ParallelEnumerable 重要方法概览: 1)public static ParallelQuery<TSource> ...