WINCE下进程间通信(一)

在WINCE开发中经常需要在不同的进程之间传递、共享数据,总结了一下,WINCE下进程间通信常用的方式有:Windows消息,共享内存,socket通信,管道,全局原子,邮槽等,下面就分别对这几种方法做个小结。(当然还可以采用注册表,磁盘文件以及数据库方式,只是这几种方式的通信效率和实时性比较低,所以一般不考虑。)

一、Windows消息

通过Windows消息,可以很方便的在进程与进程之间传递数据。对于传递像字符串这种小的数据,可以直接将字符串以消息参数wParam、lParam的方式传递给其他进程,对于大一点的数据,可以采用发送WM_COPYDATA消息,参考代码如下:

  1. void SendMsg(HWND hwnd,LPVOID lpData,DWORD dwSize)
  2. {
  3. // 填充COPYDATASTRUCT结构
  4. COPYDATASTRUCT cpd;
  5. cpd.cbData = dwSize;
  6. cpd.lpData = lpData;
  7. // 向指定窗口发送WM_COPYDATA消息,不能用PostMessage方式发送
  8. ::SendMessage(hwnd, WM_COPYDATA, NULL,(LPARAM)&cpd);
  9. }
  10. // 发送端
  11. TCHAR *data=_T("要发送的内容");
  12. 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消息的处理

  1. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. PAINTSTRUCT ps;
  4. HDC hdc;
  5. TCHAR data[256]={0};
  6. switch (message)
  7. {
  8. case WM_COPYDATA:
  9. {
  10. COPYDATASTRUCT *pCopyDataStruct=(COPYDATASTRUCT *)lParam;
  11. memcpy(data,pCopyDataStruct->lpData,pCopyDataStruct->cbData);
  12. }
  13. break;
  14. // ...
  15. }
  16. return DefWindowProc(hWnd, message, wParam, lParam);
  17. }

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:

  1. /*******************************************************************
  2. filename: CShareMemory.h
  3. purpose:   封装了共享内存操作类
  4. author:    firehood
  5. created:   2011.03.16
  6. ********************************************************************/
  7. #ifndef _SHARE_MEMORY_H
  8. #define _SHARE_MEMORY_H
  9. class CShareMemory
  10. {
  11. public:
  12. CShareMemory();
  13. ~CShareMemory();
  14. public:
  15. /**********************************************************
  16. 函数名:Open
  17. 功能:  创建或打开内存映射文件
  18. 参数:
  19. [in]szMapName:      要创建的共享内存名称
  20. [in]dwSize:         创建共享内存的大小
  21. 返回值:
  22. 0:      失败
  23. 1:      创建成功
  24. 2:      文件已存在
  25. ***********************************************************/
  26. DWORD Open(LPCTSTR szMapName,DWORD dwSize);
  27. /**********************************************************
  28. 函数名:Read
  29. 功能:  从共享内存指定位置读取数据
  30. 参数:
  31. [out]pBuf:          存放读取的数据
  32. [in]dwSize:         读取数据的大小
  33. [in]dwOffset        距共享内存起始位置的偏移量
  34. 返回值:
  35. TRUE: 成功 FALSE:失败
  36. ***********************************************************/
  37. BOOL Read(void* pBuf,DWORD dwSize,DWORD dwOffset = 0);
  38. /**********************************************************
  39. 函数名:Write
  40. 功能:  从共享内存指定位置写入数据
  41. 参数:
  42. [in]pBuf:           待写入的数据指针
  43. [in]dwSize:         写入数据的大小
  44. [in]dwOffset        距共享内存起始位置的偏移量
  45. 返回值:
  46. TRUE: 失败 FALSE:失败
  47. ***********************************************************/
  48. BOOL Write(const void* pBuf,DWORD dwSize,DWORD dwOffset = 0);
  49. void Close(void);
  50. private:
  51. HANDLE m_hShareMemory;
  52. LPVOID m_pMapBuffer;
  53. HANDLE m_hAccessMutex;
  54. };
  55. #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:

  1. #include "stdafx.h"
  2. #include "CShareMemory.h"
  3. CShareMemory::CShareMemory()
  4. {
  5. m_hShareMemory = NULL;
  6. m_pMapBuffer = NULL;
  7. m_hAccessMutex =NULL;
  8. }
  9. CShareMemory::~CShareMemory()
  10. {
  11. Close();
  12. }
  13. DWORD CShareMemory::Open(LPCTSTR szMapName,DWORD dwSize)
  14. {
  15. DWORD dwRet = 1;
  16. if(szMapName == NULL)
  17. return 0;
  18. if(m_hShareMemory)
  19. {
  20. Close();
  21. }
  22. // 创建内存映射文件对象
  23. m_hShareMemory = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,dwSize,szMapName);
  24. if(!m_hShareMemory)
  25. {
  26. return 0;
  27. }
  28. // 内存映射文件对象已存在
  29. if(GetLastError() == ERROR_ALREADY_EXISTS)
  30. {
  31. dwRet = 2;
  32. }
  33. // 获取内存映射文件指针
  34. m_pMapBuffer = MapViewOfFile(m_hShareMemory,FILE_MAP_ALL_ACCESS,0,0,0);
  35. if(!m_pMapBuffer)
  36. {
  37. CloseHandle(m_hShareMemory);
  38. return 0;
  39. }
  40. // 创建互斥体,用于读写同步
  41. TCHAR szMutexName[MAX_PATH];
  42. _tcscpy(szMutexName, szMapName);
  43. _tcscat(szMutexName, _T("_Mutex"));
  44. m_hAccessMutex=CreateMutex(NULL, FALSE, szMutexName);
  45. if(!m_hAccessMutex)
  46. {
  47. Close();
  48. return 0;
  49. }
  50. return dwRet;
  51. }
  52. BOOL CShareMemory::Read(void* pBuf,DWORD dwSize,DWORD dwOffset)
  53. {
  54. BOOL bRet;
  55. if(!m_pMapBuffer) return FALSE;
  56. if(WaitForSingleObject(m_hAccessMutex,INFINITE)==WAIT_OBJECT_0)
  57. {
  58. memcpy(pBuf,(BYTE*)m_pMapBuffer+dwOffset,dwSize);
  59. bRet = TRUE;
  60. }
  61. ReleaseMutex(m_hAccessMutex);
  62. return bRet;
  63. }
  64. BOOL CShareMemory::Write(const void* pBuf,DWORD dwSize,DWORD dwOffset)
  65. {
  66. BOOL bRet;
  67. if(!m_pMapBuffer) return FALSE;
  68. if(WaitForSingleObject(m_hAccessMutex,INFINITE)==WAIT_OBJECT_0)
  69. {
  70. memcpy((BYTE*)m_pMapBuffer+dwOffset,pBuf,dwSize);
  71. bRet = TRUE;
  72. }
  73. ReleaseMutex(m_hAccessMutex);
  74. return TRUE;
  75. }
  76. void CShareMemory::Close(void)
  77. {
  78. if(m_hShareMemory)
  79. {
  80. UnmapViewOfFile(m_pMapBuffer);
  81. CloseHandle(m_hShareMemory);
  82. m_pMapBuffer = NULL;
  83. m_hShareMemory = NULL;
  84. }
  85. if(m_hAccessMutex)
  86. {
  87. CloseHandle(m_hAccessMutex);
  88. m_hAccessMutex = NULL;
  89. }
  90. }

WINCE下进程间通信(一)的更多相关文章

  1. WINCE下进程间通信(二)

    WINCE下进程间通信(二) 接着前面的文章<WINCE下进程间通信(一)>,现在介绍进程间通信的另一种方法. 三.管道(消息队列) WINCE并不支持类似于PC机上匿名管道.命名管道的通 ...

  2. WinCE下读取注册表获得SD路径

    WinCE下读取注册表获得SD路径 [要点]WinCE注册表中[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory\] 下键Folde ...

  3. WinCE下GPRS自动拨号软件(GPRS AutoDial)

    之前在WinCE下调试USB的3G Modem时,写过一个拨号助手RASManager,基本能用.后来车机卖到俄罗斯去,客户老M提供了一个更好的GPRS自动拨号软件GPRS AutoDial,功能完善 ...

  4. Wince下sqlce数据库开发(二)

    上次写到使用数据绑定的方法测试本地sqlce数据库,这次使用访问SQL Server的方法访问sqlce,你会发现他们是如此的相似... 参考资料:http://www.cnblogs.com/rai ...

  5. Wince下sqlce数据库开发(一)

    对于Wince下的sqlce数据库虽然很多人在用,但在我查找资料时,却发现资料是多么的匮乏,在此对自己这几天的了解做个简单介绍,希望对大家能有所帮助! 本文的最后附有所使用到的sqlce在wince下 ...

  6. 浅析Linux下进程间通信:共享内存

    浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...

  7. 在Window Embedded CE(Wince)下使用OpenNETCF进行路由表的开发

    点击打开链接 背景 在开发3G项目的是时候,发现尽管3G网络连接已经建立成功了,但是数据不能发送成功,查明原因,由于路由表的问题,导致数据往ActiveSync连接的对端,也就是PC发送,而不是发送到 ...

  8. WinCE下使用C#获得带毫秒的DateTime.Now

    在WinCE下,使用DateTime.Now获取的系统时间是不带毫秒的,如果想要它带毫秒,需要耍点手段.话不多说,直接上代码: public static DateTimePrecisely { // ...

  9. wince下sources\sources.cmn\Makefile.def的相关作用

    1:首先是Makefile.def: ---------------------------------------- 在所有驱动的makefile中有!INCLUDE $(_MAKEENVROOT) ...

随机推荐

  1. sql语句-排序后加入序号再运算判断取想要的项

    select a.id as aid,b.id as bid,a.city,a.cang,a.sid,a.time as atime,b.time as btime,a.price as aprice ...

  2. C# var 隐式类型 var 用法 特点

    var 关键字是C# 3.0 开始,在方法范围中声明的变量: var有以下特点: * 1.var在编译器编译的时候根据初始值推断出其的类型          * 2.不能赋值除了初始值类型之外的其他类 ...

  3. NGUI实现一个背包功能

    界面布局是这样的,一个400*400的背景,然后在其上是16张小图片,每个小图片格子可以用来放置拾取的物品.有两个预制体,一个是可放置的小格子,一个是拾取的物品(包含一个此物品有多少的Label). ...

  4. 类型“GridView”的控件必须放在具有 runat=server 的窗体标记内?

    Response.AddHeader("content-disposition", "attachment;filename=CRM.xls") Respons ...

  5. JavaScript高级程序设计:第二章

    在HTML中使用JavaScript 1.<script>元素:向HTML页面中插入JavaScript的主要方法就是使用<scritp>元素.HTML4.01为<scr ...

  6. POJ 1611 The Suspects(简单并查集)

    ( ̄▽ ̄)" #include<iostream> #include<cstdio> using namespace std; ]; void makeSet(int ...

  7. hdu_2899_Strange fuction(三分查找)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2899 题意:让你解方程 题解:对于只有一个凸或者没有凸的图像,可以直接上三分解决. #include& ...

  8. 利用DataImportHandler建索引时一直无法完成

    问题研究 项目中需要利用DataImportHandler从hive中sync数据到solr.发现有时候hive sql已经执行完几个小时了,sync任务还没有完成,貌似哪里卡住了.重启solr后重新 ...

  9. LeetCode OJ 95. Unique Binary Search Trees II

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  10. R语言笔记3--实例1

    综合性例子: 模拟产生统计专业同学的名单(学号区分),记录数学分析,线性代数.概率统计三科成绩,然后进行一些统计分析 1.首先产生一个向量(100个元素,代表100位学生) 2.模拟成绩 runif: ...