如何从一个流程向多个其他流程发出信号?

时间:2016-04-13 09:36:19

标签: c++ windows ipc

我想发送一个"信号/通知"从一个流程到多个其他流程,但似乎并不能直接解决我使用Win API所做的事情:

  • 无法在进程之间共享条件变量。

  • 事件对象似乎从一个线程发出信号(使用自动重置事件)或多个(手动重置事件),但我需要手动关闭信号。然后可能很难知道所有的观察者"已经确认了这个信号。

我也使用过Boost的IPC同步,但我并不喜欢这个实现,因为互斥锁并没有放弃" -state as windows counter-part(如果使用互斥锁的软件崩溃,很难从中恢复)。

有什么建议吗?基本上我想使用一个条件变量,但它应该适用于多个进程。谢谢!

澄清:

基本上这就是我正在做的事情:我正在从一个进程更新共享内存(让它称之为控制器),这需要通知多个进程(观察者)共享内存已更新。

我使用boost时所做的是使用共享(IPC)互斥锁和条件变量。条件变量将在每个观察者的单独线程中等待,直到控制器通知它从共享内存中读取。在观察者从共享存储器中读取之后,它将返回以等待来自控制器的另一通知。如何使用Win API执行此操作?

1 个答案:

答案 0 :(得分:1)

最简单的方法是使用RegisterWindowMessage和PostMessage广播窗口消息。每个观察者都有一个单独的线程,它创建一个不可见的窗口并运行一个消息处理循环,在控制器发出信号时通知主线程。

这种方法的主要限制是观察者和控制器都必须在同一个桌面上以及相同的用户上下文和权限级别上运行。

如果由于某种原因你想避免使用GUI,并坚持内核同步功能,我认为你需要多个事件对象。

执行此操作的一种简单方法是将计数器放在共享内存中,并使用它来确定事件对象名称。我们还将使用单个互斥锁来协调访问,并从一个手动重置事件对象开始,最初未设置。

当控制器想要向观察者发出信号时,它会:

  1. 声明互斥锁。

  2. 发信号然后关闭当前事件对象。 (注意,对象将继续存在,直到最后一个观察者关闭它。)

  3. 递增计数器。

  4. 创建一个新的手动重置事件对象,最初未设置,用于下一个信号。

  5. 释放互斥锁。

  6. 当观察者想要等待信号时:

    1. 声明互斥锁。

    2. 打开由计数器当前值指示的事件对象。

    3. 释放互斥锁。

    4. 等待事件对象发出信号,然后将其关闭。

    5. (您可以通过消除互斥锁并使用互锁操作来提高效率。您只需要更加谨慎地处理事务的顺序,并处理边缘情况,例如事件在您尝试打开对象之前删除对象。)

      另一个选择是每个观察者有一个自动重置事件对象。但随后观察者需要向控制器注册,并且控制器必须在意外终止的观察者之后检测并清理。这不会特别困难,但完整的描述将是乏味的,我不认为你会比以前的建议获得更多的东西。

      此变体将使用命名管道。命名管道的优点是您可以注意注册观察者并使用相同的API通知他们,并且(如果您已经做好了一切),如果另一端意外死亡,您将自动收到通知。缺点是API具有相当陡峭的学习曲线。

      当然也有使用固定数量的内核对象的解决方案some of which are described here.但是,对于我来说,如何将这些对象调整到其中一个观察者可能意外退出的情况并不明显。

      为了记录,虽然我试图按照要求回答问题,但在您的特定情况下,我怀疑您需要阻止控制器修改共享内存,而任何观察者仍在阅读它,我认为这将对可行的方法产生重大影响。这不是微不足道的;首先,您需要考虑如何处理从共享内存中读取时需要花费意外时间的观察者 - 控制器最终应该超时吗?如果是这样,它应该杀死有问题的观察者,还是让它运行但忽略它,或者......?

      (因为我不确切知道这个修改过的场景会是什么样子,所以我没有多想,但我的第一直觉就是使用命名管道。)

相关问题