进程间通信 --windows篇

36 篇文章 0 订阅

   需求如下: 当配置文件发生改变时,广播配置信息给所有的进程,通知其重装配置. 

   1. WM_COPYDATA传递消息

   windows下最简单进程通信方式,利用WM_COPYDATA事件, 该事件能够传递一指针来携带消息. 

   

// 查找标题为Sample的窗口,向其发送一字符串
HWND hWnd = FindWindowW(NULL, "Sample");
if (hWnd != NULL) 
{
	this->setWindowTitle("dialog_send");

	char szMsg[512];
        strcpy(szMsg,"hello world");

	COPYDATASTRUCT cpd;
	cpd.dwData = 0;
	cpd.cbData = strlen(szMsg);
	cpd.lpData = szMsg;
	
	// 同步发送消息
	SendMessageW(hWnd, WM_COPYDATA, NULL, (LPARAM)&cpd);
}

 

    这里就有一个问题,WM_COPYDATA消息,只能使用 SendMessage (同步发送消息,必须等待消息被处理完成才返回), 不能使用PostMessage(异步), 这样远远达不到实时要求. 测试了一下,发现大部分消息都只能采样同步方式发送, WM_CLEAR / WM_NOTIFYFORMAT / WM_USER / WM_DEVICECHANGE 等消息可以通过异步发送. 

  

   在不同进程之间传递一指针,各个进程其对应指针地址不同, 不可能取到相应字符串的值. 实际上WM_COPYDATA内部实现也用到共享内存, 那我们采用 windows消息通知 + 共享内存 来实现通知重装配置功能.

 

   2. windows 广播消息

/**
 * windows 下提供了强大的广播消息函数,可以向网络驱动,应用程序,安装的驱动,系统级设备及组件发送消息
 */
DWORD bsm_app=BSM_APPLICATIONS; // 向所有应用程序发送消息
BroadcastSystemMessage(BSF_POSTMESSAGE,&bsm_app,WM_NOTIFYFORMAT,NULL,NULL);

 

   3. windows下共享内存

   服务端:

#include <windows.h>
#include <stdio.h>

#define MY_MEMORY_ID "kettas"

int main(int argc,char **argv)
{
	/**
	 *  创建命名为kettas的共享内存
	 *  dwMaximumSizeLow 映射对象低位最大尺寸设置为0时, xp下创建失败,这里设置为1024
	 */ 
	HANDLE lhShareMemory = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,1024,MY_MEMORY_ID);  
	if (lhShareMemory !=NULL)  
	{  
		printf("信息:共享数据打开失败");
		return 1;
	}  
	
	LPVOID buff;  
	buff = MapViewOfFile(lhShareMemory,FILE_MAP_WRITE,0,0,0); // 获取映射对象地址
	// strcpy(strBuffer,"hello kettas"); // 写入数据
	
	char *str="Hello world";
	CopyMemory((PVOID)buff,str,strlen(str)); // 写入数据

	UnmapViewOfFile((PVOID)buff);

	getchar();
	return 0;
}

   客户端:

#include <windows.h>
#include <stdio.h>

#define MY_MEMORY_ID "kettas"

int main(int argc,char **argv)
{
	HANDLE  handleFile;
	handleFile= OpenFileMapping(FILE_MAP_ALL_ACCESS,false,MY_MEMORY_ID); //打开共享文件
	if (handleFile==NULL)
	{
		printf("共享数据打开失败\n");
		return 1;
	}

	char * str = NULL;
	str=(char *) MapViewOfFile(handleFile,FILE_MAP_ALL_ACCESS,0,0,0); // 获取共享对象数据
	
	printf("结果:%s",str);
	
	UnmapViewOfFile(str);
	CloseHandle(handleFile);
	
	getchar();
	return 0;
}

 

  当配置发生改变时, 服务端将数据写入共享内存,然后广播通知其它进程去共享内存中获取相应数据. 对于QT控制台程序,利用上往篇讲的, 新建一窗口后隐藏即可

/**
 * @brief 获取广播消息
 * @parm  MRev 消息回调函数
 */ 
void GetNoticeMessage( MRev mRev )
{
	if(mRev==NULL)
	{
		printf("错误:回调函数为空\n");
		return;
	}

	// 全局指针赋值
	GRevHandler=mRev;

#ifdef WIN32
	hinstance = (HINSTANCE)GetModuleHandle(NULL);

	if (!InitApplication(hinstance)) 
	{
		printf("错误:注册窗口失败\n");
		return;
	}

	if (!InitInstance(hinstance, SW_HIDE)) // 隐藏窗口
	{
		printf("错误:新建窗口失败\n");
		return;
	}

#elif __unix
	// 安装消息
	InstallMessage();
#endif 
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值