如何从一个进程向多个其他进程发送信号

How to signal from one process to multiple other processes?

本文关键字:进程 信号 其他 一个      更新时间:2023-10-16

我想从一个进程向多个其他进程发送"信号/通知",但似乎没有一个直接的解决方案来解决我想使用Win API:

  • 不能在进程之间共享条件变量。

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

我也使用过Boost的IPC同步,但我真的不喜欢它的实现,因为互斥体没有作为窗口计数器部分的"放弃"状态(如果使用互斥体的软件崩溃,很难从中恢复)。

有什么建议吗?基本上,我想使用一个条件变量,但它应该跨多个进程工作。非常感谢。


澄清:

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

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

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

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


无论出于何种原因,如果您希望避免使用GUI,并坚持使用内核同步功能,我认为您将需要多个事件对象。

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

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

  1. 声明互斥对象。

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

  3. 递增计数器。

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

  5. 释放互斥对象。

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

  1. 声明互斥对象。

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

  3. 释放互斥对象。

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

(你可以通过消除互斥并使用互锁操作来提高效率。你只需要对做事的顺序更加小心,并处理边缘情况,比如在你试图打开事件对象之前删除了它。)


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

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


当然,也有使用固定数量内核对象的解决方案,其中一些在这里进行了描述。然而,对于我来说,如何使这些适应其中一名观察员可能意外退出的情况并不明显。


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

(由于我不知道这个修改后的场景会是什么样子,所以我没有多想,但我的第一反应是使用命名的管道。)