WINCE下进程间通信(一)

WINCE下进程间通信(一)

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

一、Windows消息

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

[cpp] view plaincopyprint?

  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消息的处理

[cpp] view plaincopyprint?

  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:

[cpp] view plaincopyprint?

  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:

[cpp] view plaincopyprint?

  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. }
时间: 2024-10-02 02:56:47

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

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

在WinCE下,使用DateTime.Now获取的系统时间是不带毫秒的,如果想要它带毫秒,需要耍点手段.话不多说,直接上代码: public static DateTimePrecisely { //定义一个全局变量,用来保存一个毫秒的0点. private static int m_offset = 0; static DateTimePrecisely() { int s = DateTime.Now.Second; //我们需要等待一次跨秒,来定义毫秒的0点. while (true) {

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

之前在WinCE下调试USB的3G Modem时,写过一个拨号助手RASManager,基本能用.后来车机卖到俄罗斯去,客户老M提供了一个更好的GPRS自动拨号软件GPRS AutoDial,功能完善且强大,RASManager基本就废弃了. GPRS AutoDial的使用方法如下图所示. GPRS AutoDial v1.4.3下载地址,http://files.cnblogs.com/files/we-hjb/GPRS_AD_1.4.3.rar

Wince下sqlce数据库开发(二)

上次写到使用数据绑定的方法测试本地sqlce数据库,这次使用访问SQL Server的方法访问sqlce,你会发现他们是如此的相似... 参考资料:http://www.cnblogs.com/rainman/archive/2012/03/13/2393975.html 本文的最后附有本次测试的全部代码,大家可以去下载.当然,我更希望这里作为一个交流的平台,能够相互的学习,如果你们有其他的想法希望可以告诉我 注:开发环境VS2008       开发语言:C# 1.创建Wince下的Winfo

Wince下sqlce数据库开发(一)

对于Wince下的sqlce数据库虽然很多人在用,但在我查找资料时,却发现资料是多么的匮乏,在此对自己这几天的了解做个简单介绍,希望对大家能有所帮助! 本文的最后附有所使用到的sqlce在wince下的安装文件,wince截屏工具及本示例代码的下载地址. 1.创建wince项目: 注:wince项目的创建需要在VS2008或者VS2005下 图1 创建“智能设备项目” 2.制作主界面 为主界面添加两个控件,分别为:datagrid和button,分别用于数据显示和功能控制. 图2 制作主界面 3

如何生成一个 WinCE 下文件全路径大于 MAX_PATH(260) 字节的文件路径?

大家都知道,在 Windows 系统中文件名的路径最大值是 MAX_PATH.例如:Windows XP 系统,对文件名的长度进行测试: (1) 在分区 E:\ 的根目录新建一个文件,其文件名最大长度为: 255.---全路径长度>>> 258(2) 在分区 E:\ 子目录 Program Files\ 中新建一个文件,其文件名的最大长度为: 242. ---全路径长度>>>259在 WinCE 系统下,也有一定的限制.另外,如果试图将在 E:\ 根目录新建的最大文件名

Wince下演示系统自启动/加载dll方法

前面我们已经介绍过了Wince开机画面,自启动方法了. 今天主要是介绍我们演示系统是如何实现的自运行和加载Dll的方法. 之前我们碰到的主要问题是这样的: 1.在catalog items下加载 Sotorage Devices--MSFLash- Drivers--Flash MDD. 这样,Wince下就可以看到NandFlash的盘符,并且修改注册表/校准鼠标后都可以保存下来. 但是,此时是不能用飞凌提供的程序自启动的,且dll也无法自动加载. 2.在catalog items下不加载 S

Linux下进程间通信之命名管道(FIFO)

匿名管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信.在命名管道(FIFO)提出后,该限制得到了克服.FIFO不同于pipe在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中.命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够相互通信. FIFO总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出. Linux下有两种方式创建FIFO,一是在shell下交互的建立一个命名管道,二是在程序中使用系统函

Windows下进程间通信及数据共享

进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码.数据以及它可利用的系统资源(如文件.管道等)组成.多进程/多线程是Windows操作系统的一个基本特征.Microsoft Win32应用编程接口(Application Programming Interface, API)提供了大量支持应用程序间数据共享和交换的机制,这些机制行使的活动称为进程间通信(InterProcess Communication, IPC),进程通信就是指不同进程间进行数据共享和数据交换. 进程通

windows下进程间通信方法

摘 要 随着人们对应用程序的要求越来越高,单进程应用在许多场合已不能满足人们的要求.编写多进程/多线程程序成为现代程序设计的一个重要特点,在多进程程序设计中,进程间的通信是不可避免的.Microsoft Win32 API提供了多种进程间通信的方法,全面地阐述了这些方法的特点,并加以比较和分析,希望能给读者选择通信方法提供参考.关键词 进程 进程通信 IPC Win32 API 1 进程与进程通信 进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码.数据以及它可利用的系统资源