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. PHP常用函数之数组篇

    分类:数组分为索引数组和关联数组.索引数组既是指的我们的数组下表为阿拉伯数字,关联数组则是非阿拉伯数字. 定义: 5.4版本之前 $arr = array('name' => '张三', 'ag ...

  2. vmware 命令行启动虚拟机

    在redhat enterprise 5.3安装了vmware workstation,如何用vmware 命令行启动指定虚拟机?/usr/bin/vmware[root@node0 ~]# /usr ...

  3. LeetCode OJ 220.Contains Duplicate 3

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

  4. BFS and Queue

    BFS (Bridth First Search) can be implemented by a queue. Procedure is like this: (Q is Queue) 1, Put ...

  5. 浅谈 qmake 之 shadow build

    shadow build shadow build 是什么东西?就是将源码路径和构建路径分开(也就是生成的makefile文件和其他产物都不放到源码路径),以此来保证源码路径的清洁. 这不是qmake ...

  6. IntelliJ IDEA 2016.1.3激活【亲测可用】

    测试日期:2016.6.24 License server: http://www.iteblog.com/idea/key.php // ========================= 更多技术 ...

  7. zookeeper集群实例

    zookeeper是什么 Zookeeper,一种分布式应用的协作服务,是Google的Chubby一个开源的实现,是Hadoop的分布式协调服务,它包含一个简单的原语集,应用于分布式应用的协作服务, ...

  8. gnome3

    http://askubuntu.com/questions/67753/how-do-i-add-an-application-to-the-dash https://wiki.gnome.org/ ...

  9. 1.1 整理的Linux 基础

    本文总参照:http://blog.csdn.net/xiaoguaihai/article/details/8705992/ 2.用户管理操作命令 (1)Su - XX 切换用户 3.文件管理操作命 ...

  10. VS2010 自定义向导

    最近在学OpenGL,不想使用OpenGL的GLUT工具,自己写了一个初始化OpenGL的类,并在win32中使用,每次都要新建一个win32项目,然后将OpenGL初始化类拷贝到项目,然后进行各种初 ...