河南省专业做网站公司,网站建设求职信,wordpress 4.7多用户,网站开发定制方案常见的进程间通信方法
常见的进程间通信方法有#xff1a;
管道#xff08;Pipe#xff09;消息队列共享内存信号量套接字
下面#xff0c;我们将详细介绍消息队列的原理以及具体实现。 什么是消息队列#xff1f;
Windows操作系统使用消息机制来促进应用程序与操作系…
常见的进程间通信方法
常见的进程间通信方法有
管道Pipe消息队列共享内存信号量套接字
下面我们将详细介绍消息队列的原理以及具体实现。 什么是消息队列
Windows操作系统使用消息机制来促进应用程序与操作系统之间的通信。每当发生事件如键盘按键、鼠标移动或系统事件时操作系统都会生成相应的消息。这些消息被发送到一个特定的消息队列中随后由应用程序的消息循环处理。
消息队列
每个创建了窗口的线程都拥有一个消息队列用于存储等待处理的消息。这些消息包括用户动作如鼠标点击、键盘操作和系统通知如窗口重绘请求、系统关闭通知。
消息循环
线程通过一个循环机制称为消息循环或消息泵从其消息队列中检索消息。消息循环的基本操作包括
检索消息使用GetMessage或PeekMessage。翻译消息TranslateMessage转换键盘输入。分发消息DispatchMessage将消息派发给目标窗口的窗口过程。 消息分类
消息主要包含
系统消息涉及窗口生命周期管理如WM_CLOSE和WM_QUIT等。硬件消息反映用户与硬件的交互如WM_KEYDOWN和WM_MOUSEMOVE等。
除了上面提到的消息外用户还可以自定义消息自定义消息一般从WM_USER0x0400开始到0x7FFF这样一个范围内比如#define WM_CUSTOM_MSG WM_USER100 接口介绍
GetMessage、PeekMessage、SendMessage、PostMessage这四个接口是Windows消息处理的核心它们各自承担着不同的角色和功能。
GetMessage 原型
BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax
);参数解释
lpMsg指向MSG结构的指针该结构将接收消息的详细信息。hWnd指定窗口的句柄如果为NULL则接收属于调用线程的任何窗口的消息。wMsgFilterMin和wMsgFilterMax指定要检索的消息范围的最小值和最大值。如果两者都为0函数将返回所有可用的消息。
功能和特点
GetMessage用于从调用线程的消息队列中检索消息。该函数在有消息到达时返回如果遇到退出消息WM_QUIT则返回FALSE。该函数是阻塞的如果没有消息它会等待消息的到来。 PeekMessage 原型
BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg
);参数解释
lpMsg指向MSG结构的指针该结构将接收消息的详细信息。hWnd指定窗口的句柄如果为NULL则获取属于调用线程的任何窗口的消息。wMsgFilterMin和wMsgFilterMax指定要检索的消息范围的最小值和最大值。wRemoveMsg指定消息如何处理。常用值有PM_REMOVE、PM_NOREMOVE。
功能和特点
PeekMessage用于非阻塞地检查调用线程的消息队列允许你查看消息队列中的消息而不必移除它。可以配置为从队列中移除消息或仅检查消息而不移除。常用于动画或游戏编程中确保应用程序保持响应用户操作同时继续进行其它处理。
SendMessage 原型
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam
);参数解释
hWnd接收消息的窗口的句柄。Msg消息的标识符。wParam 和 lParam消息特定的附加信息。
功能和特点
SendMessage同步发送消息调用方在接收窗口处理该消息之前会阻塞。可用于发送任何类型的消息并且能够获取消息处理的结果。 PostMessage 原型
BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam
);参数解释
hWnd接收消息的窗口的句柄。Msg消息的标识符。wParam 和 lParam消息特定的附加信息。
功能和特点
PostMessage异步发送消息将消息放入消息队列后立即返回不等待消息被处理。适合用于那些不需要立即反馈的消息发送如状态更新或通知消息。
实现 问题
实现两个进程进程1发送消息给进程2相关代码如下
// 进程1
int main()
{HWND hWnd FindWindow(NULL, LWindowsProject1); // 找到进程2的句柄const wchar_t* message LHello!;if (hWnd ! NULL) {SendMessage(hWnd, WM_USER100, 0, (LPARAM)message);}std::cin.get();
}// 进程2
#define WM_CUSTOMMSG (WM_USER100)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case WM_CUSTOMMSG: {wchar_t* receivedMessage reinterpret_castwchar_t*(lParam);SetWindowText(hLabel, receivedMessage);}break;...}return 0;
}进程1通过自定义消息WM_USER100发送了一个字符串给进程2进程2的确收到了消息但是数据获取失败。 因为进程1准备发送的数据存储在进程1的虚拟内存中进程2是无法通过地址来获取这个数据的所以进程2虽然收到消息了但是无法得到对应的数据。 所以在进程间通过消息队列通信时需要保证传递的数据的安全性。
WM_COPYDATA
WM_COPYDATA是一个Windows消息用于在Windows应用程序之间传递数据。这个消息特别适用于跨进程通信允许一个应用程序向另一个应用程序的窗口发送数据无论这些数据是简单的数值、字符串还是更复杂的结构通。
原理
当一个应用程序需要向另一个应用程序发送数据时它可以将数据封装在COPYDATASTRUCT结构中并通过SendMessage函数发送WM_COPYDATA消息。当接收窗口的窗口过程收到这条消息时它可以从COPYDATASTRUCT结构中提取数据。
COPYDATASTRUCT结构
这个结构用于封装要传递的数据其定义如下
typedef struct tagCOPYDATASTRUCT {ULONG_PTR dwData; // 任意值由发送方设置接收方可以用它来识别数据DWORD cbData; // lpData指向的数据的大小以字节为单位PVOID lpData; // 指向要传递的数据的指针
} COPYDATASTRUCT, *PCOPYDATASTRUCT;dwData这是一个用户定义的数据值发送方可以使用它来传递额外的信息或数据类型标识接收方则可以用它来决定如何解释接收到的数据。cbData这表示 lpData 指向的数据的大小以字节为单位。lpData这是一个指针指向实际要传输的数据。
实现代码 进程1代码
int main()
{HWND hWnd FindWindow(NULL, LWindowsProject1);const wchar_t* message LHello!;if (hWnd ! NULL) {COPYDATASTRUCT cds;cds.dwData 1; // 用于识别数据的自定义标识cds.cbData (wcslen(message) 1) * sizeof(wchar_t); // 包括终止符的大小cds.lpData (void*)message;SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)cds);}std::cin.get();
}进程2代码
HWND hLabel;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{hInst hInstance; // 将实例句柄存储在全局变量中HWND hWnd CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);if (!hWnd){return FALSE;}hLabel CreateWindowW(LSTATIC, LWaiting for message...,WS_CHILD | WS_VISIBLE | SS_LEFT,10, 10, 300, 20,hWnd, (HMENU)1, hInstance, nullptr);ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE;
}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case WM_COPYDATA: {PCOPYDATASTRUCT pCds (PCOPYDATASTRUCT)lParam;if (pCds-dwData 1) {const wchar_t* receivedStr (const wchar_t*)pCds-lpData;SetWindowText(hLabel, receivedStr);}}break;case WM_COMMAND:{int wmId LOWORD(wParam);// 分析菜单选择:switch (wmId){case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}}break;case WM_PAINT:{PAINTSTRUCT ps;HDC hdc BeginPaint(hWnd, ps);// TODO: 在此处添加使用 hdc 的任何绘图代码...EndPaint(hWnd, ps);}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}效果