首页 > 技术文章 > Windows C++ 通过Event进行跨进程通讯

TssiNG-Z 2020-05-12 20:02 原文

windows中可以通过Event进行跨进程的通讯, 只要在创建事件时, 事件名相同, 就会得到同一个事件的句柄, 以此为基础可以进行跨进程通讯

先看一下msdn上的定义和解释(下面我大概翻译了一下, 具体内容参阅 : https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventa)

定义

HANDLE CreateEventA(
  LPSECURITY_ATTRIBUTES lpEventAttributes,
  BOOL                  bManualReset,
  BOOL                  bInitialState,
  LPCSTR                lpName
);

参数

lpEventAttributes

SECURITY_ATTRIBUTES 结构体的指针. 如果此参数为NULL, 则创建的Event不能被子进程继承.

bManualReset

该参数指明创建的Event当被激活后会不会自动复位, 如果这个参数为FALSE, 则每次事件被激活后, 需要手动调用ResetEvent来将事件复位.

bInitialState

如果该参数为TRUE, 则Event创建后的初始状态即为激活态.

lpName

Event的名称, 最大长度为 MAX_PATH 个字符且这个名称是大小写敏感的.

当要Create一个lpName已经存在的Event时,要确保程序拥有 EVENT_ALL_ACCESS 权限. 在Create已经创建了的Event时, 由于事件已经被创建, 当前函数调用中的bManualReset参数和bInitialState参数会被忽略, 与此同时, lpEventAttributes参数将只能决定这个Event能否被子进程进程, 而SECURITY_ATTRIBUTES中的安全描述符属性会被忽略.

如果一个拥有lpName的HANDLE已经被与CreateEvent相同命名空间中的其它函数( CreateMutex等等 )创建, 再次Create相同的lpName就会导致函数失败, 同时 GetLastError 返回 ERROR_INVALID_HANDLE. 此处还是比较容易理解的, 我们创建一把名为"张三"的锁, 然后再创建一个名为"张三"的事件, Windows不允许这种事情发生.

如果不想让创建的Event成为公共的, 参阅 : https://docs.microsoft.com/zh-cn/windows/win32/termserv/kernel-object-namespaces  和  https://docs.microsoft.com/zh-cn/windows/win32/sync/object-namespaces

返回值

成功返回HANDLE, 失败返回 NULL. 可以使用 GetLastError 来检查错误

 

下面是两个进程间使用Event通讯的例子

激活事件进程

 1 #include <iostream>
 2 #include <Windows.h>
 3 
 4 int main()
 5 {
 6   HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, "helloWorld");
 7   
 8   while (true)
 9   {
10     std::cout << "set event : helloWorld" << std::endl;
11 
12     SetEvent(hEvent);
13 
14     Sleep(5000);
15   }
16 
17   return 0;
18 }

 

等待事件进程

 1 #include <iostream>
 2 #include <Windows.h>
 3 
 4 int main()
 5 {
 6   HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, "helloWorld");
 7 
 8   while (true)
 9   {
10     WaitForSingleObject(hEvent,INFINITE);
11 
12     std::cout << "helloWorld" << std::endl;
13 
14     ResetEvent(hEvent);
15   }
16 
17   return 0;
18 }

 

编译运行后两进程结果如下( 两个窗口叠放在一起了, 看着有点晕 )

 

 

以上, 如有疏漏错误, 欢迎指正

推荐阅读