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) ...
随机推荐
- 我的C笔记
最近更新: 1,父进程fork一个子进程,当向父进程发送一个SIGINT或其它信号时,子进程是否会接受到该信号? 2,父进程调用system执行一个程序时,向父进程发送一个信号时,system运行中的 ...
- jax-rs的客户端完整实例
本地接口: @Override public Response formsubGet(String accountContent, char inputContent, S ...
- 使用PLSQL Developer连接Oracle Database 11g Express Edition
要使用oracle数据库,需要准备三部分: 1.oracle服务端 2.oracle客户端 3.连接工具 你装的Oracle Database 11g Express Edition就是服务端,pls ...
- log4j之mybatis配置
简单记录一下,配置,因为项目要转向maven架构,所以jar有maven管理,配置完成之后发现原先的sql语句都出不来了,于是搜了一下 mybatis+log4j所需要的依赖如下(我列出我用的版本): ...
- zk reconnect
http://blog.csdn.net/hengyunabc/article/details/41450003 http://blog.csdn.net/hengyunabc/article/det ...
- 这几天用到的 Linux 命令
下面总结一下这几天用到的linux 命令,记录一下: 13 netstat -atunlp 26 apt-get install python-pip 27 pip install shadowsoc ...
- sql优化__rownum的使用【转】
ROWNUM的概念ROWNUM是一个虚假的列.它将被分配为 1,2,3,4,...N,N 是行的数量.一个ROWNUM值不是被永久的分配给一行 (这是最容易被误解的).表中的某一行并没有标号:你不可以 ...
- Lua 垃圾收集机制
1. 问题:一款用Lua做的游戏,玩了一段时间后会变卡 因为知道lua是有自动管理内存的机制,所以之前一直没有关注过lua内存的问题.所以今天好好的查看了lua垃圾收集机制.看了一下Lua的Garba ...
- Hibernate 系列教程4-单向多对一
项目图片 hibernate.cfg.xml <mapping resource="com/jege/hibernate/one/way/manytoone/User.hbm.xml& ...
- PHP全选择删除功能
<script type="text/javascript" language="javascript"> function selectBox(s ...