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

Posted

技术标签:

【中文标题】如何从一个进程向多个其他进程发出信号?【英文标题】:How to signal from one process to multiple other processes? 【发布时间】:2016-04-13 09:36:19 【问题描述】:

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

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

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

我也使用了 Boost 的 IPC 同步,但我不太喜欢这种实现,因为互斥体没有“放弃”状态作为 Windows 对应部分(如果使用互斥体的软件崩溃,它是很难从中恢复)。

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


澄清:

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

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

【问题讨论】:

您是否在与任意数量的“听众”打交道,而您事先并不知道? “监听器”是否以任何方式向“控制器”注册? notify_all() cplusplus.com/reference/condition_variable/condition_variable 怎么样 @Marichyasana:据我了解,这不适用于跨流程边界。 @IInspectable 是的,任意数量的听众。不,我可以在共享内存中添加某种计数器,但是我不确定是否有可能检测到其中一个侦听器是否会崩溃 你能用Sockets吗? 【参考方案1】:

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

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


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

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

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

    声明互斥体。

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

    增加计数器。

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

    释放互斥锁。

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

    声明互斥体。

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

    释放互斥锁。

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

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


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

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


当然也有使用固定数量内核对象的解决方案,some of which are described here. 但是,我不清楚如何使这些解决方案适应观察者可能意外退出的情况。


作为记录,尽管我已尝试按要求回答问题,但在您的特定情况下,我怀疑您需要防止控制器在任何观察者仍在阅读共享内存时修改共享内存,我认为这将对可行的方法产生重大影响。这不是微不足道的。一方面,您需要考虑如何处理在读取共享内存时花费了意想不到的时间的观察者——控制器最终是否会超时?如果是这样,它应该杀死有问题的观察者,还是让它运行但忽略它,或者......?

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

【讨论】:

以上是关于如何从一个进程向多个其他进程发出信号?的主要内容,如果未能解决你的问题,请参考以下文章

如何从信号处理程序内部向其他进程发送通知?

Python多处理:向所有进程发出事件信号的最快方法?

向同一进程中的另一个线程发出信号

从另一个 Java 进程发出信号

如何在不丢失信号的情况下将信号从多个子进程发送到主进程?

linux 信号处理