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. VC MFC工具栏(CToolBar)控件

    一.工具栏 工具栏控件在控件面板里没有对应的选项(图标),但有一个工具栏控件类CToolBar,所以我们如果要创建一个工具栏控件并显示在窗口里的话,只能用代码来完成,事实上任何一种控件,都可以用代码创 ...

  2. glusterfs——volume管理

    Q: 常用的命令有哪些? 创建volume: gluster volume create NAME stripe SCOUNT replica RCOUNT transport TYPE  BRICK ...

  3. hdu_5029_relief grain(树链剖分)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5029 题意:给你一个树,然后给你两点,将这两点之间的点涂上颜色,问涂色最多的那个颜色是什么,如果数量相 ...

  4. hdu_1348_Wall(凸包)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1348 题意:让你求n个点的凸包,凸包离点的距离为l 题解:就凸包周长+一个半径为l的圆周长 #incl ...

  5. NSBundle的用法

    bundle是一个目录,其中包含了程序会使用到的资源. 这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in). 对应bundle,cocoa提供了类NSBu ...

  6. 树形dp Codeforces Round #364 (Div. 1)B

    http://codeforces.com/problemset/problem/700/B 题目大意:给你一棵树,给你k个树上的点对.找到k/2个点对,使它在树上的距离最远.问,最大距离是多少? 思 ...

  7. 用GDB调试程序的设置 Segmentation fault(Core Dump)调试

    在写wifi库的时候碰见一个 Segmentation fault(Core Dump) 所以需要用GDB调试下. 在cmake的时候,修改CMakeLists.txt set(CMAKE_C_FLA ...

  8. linq any() all() 返回true 或者false

    一.any()只要有一个符合条件就返回true static void Main(string[] args) { //any 有符合条件的就返回true ,,,,,,,,,}; ); Console ...

  9. 收缩sql server数据库日志

    项目中,可能数据库(sql server数据库)日志太多,占了很多磁盘空间,可以通过收缩数据库日志,减少日志文件大小. 下面以Northwind数据库为例: 1.把数据库的恢复模式设置为“简单模式”: ...

  10. C++函数后面的throw()

    看CImage函数实现的时候发现了这么个东东  inline HBITMAP CImage::Detach() throw() 它是函数提供者和使用者的一种君子协定,标明该函数不抛出任何异常. 之所以 ...