Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何等待未知数量的进程结束_C++_Winapi_Synchronization - Fatal编程技术网

C++ 如何等待未知数量的进程结束

C++ 如何等待未知数量的进程结束,c++,winapi,synchronization,C++,Winapi,Synchronization,场景: 一台机器上运行着几个进程。名称和句柄未知,但它们都有一段在我们控制下运行的代码 运行命令行进程。它向其他进程发出需要结束的信号(SetEvent),我们的代码在其他进程中拾取并处理该事件 目标: 命令行进程需要等待其他进程结束。如何做到这一点 我想到的只是设置一些共享内存或其他东西,让每个进程将其句柄写入其中,以便命令行进程可以等待它们,但这似乎需要付出很多努力。必须有一些内核级的引用计数可以等待 编辑1: 我在想也许把进程分配给一个作业对象,然后命令行进程就可以等待了?虽然不太理想 编

场景:

一台机器上运行着几个进程。名称和句柄未知,但它们都有一段在我们控制下运行的代码

运行命令行进程。它向其他进程发出需要结束的信号(SetEvent),我们的代码在其他进程中拾取并处理该事件

目标:

命令行进程需要等待其他进程结束。如何做到这一点

我想到的只是设置一些共享内存或其他东西,让每个进程将其句柄写入其中,以便命令行进程可以等待它们,但这似乎需要付出很多努力。必须有一些内核级的引用计数可以等待

编辑1:

我在想也许把进程分配给一个作业对象,然后命令行进程就可以等待了?虽然不太理想

编辑2:


无法使用作业对象,因为它会干扰使用作业的其他内容。所以现在我认为进程将获得某个/任何同步对象(信号量、事件等)的句柄,命令行进程将轮询其存在性。它必须像等待一样进行轮询,这样才能使对象保持活动状态。当进程死亡时,同步对象将被windows清除,因此下一次轮询将指示没有进程。这不是一个很好的、最干净的方法,但是对于它需要做的工作来说足够简单。这方面有什么进展吗?

您可以采用以下方法之一

共享内存(内存映射对象):创建文件映射,然后MapViewOfFile-->继续请求。取消pviewfile。关闭文件

命名管道:为每个应用程序创建命名管道。并继续运行线程来读取文件。因此,您可以通过连接到该命名管道,从应用程序编写结束协议。(你可以实现一个类似的小型数据库)

WinSock:(如果进程数量较多,请不要使用。因为您需要向另一个进程发送结束请求。该进程应绑定到您的应用程序,或者应在端口中侦听。)


创建文件/DB:在进程之间共享文件。(如果需要,您可以有多个文件)。在读或写之前进行锁定。

我会考虑使用两个对象:

的解决方案。
  • 在请求其他进程终止(调用
    SetEvent()
    )之前,由主(控制器?)应用程序创建的共享信号量对象,初始计数为0。我假设其他进程没有创建此事件对象,如果尚未创建,也不会失败
  • 由其他(子进程?)进程创建的互斥对象,不用于等待它,而是用于允许主进程检查其存在(如果所有子进程终止,则应销毁它)。互斥对象具有可由多个进程“创建”的区别(根据文档)
同步如下:

  • 初始化时的子进程应创建互斥对象(将初始所有权设置为
    FALSE
  • 接收到终止请求的子进程应将信号量计数增加一(
    ReleaseSemaphore()
    ),然后正常退出
  • 主进程将进入一个循环,在信号量上调用
    WaitForSingleObject()

这种设置避免了创建进程间通信方案(例如让子进程回发它们的句柄-其数量无论如何都是未知的),而严格来说也不是“轮询”。好吧,这涉及到一些超时(有些人可能会认为这只是轮询),但是检查也是在每个进程报告它正在终止后执行的(您可以使用一些跟踪来查看超时实际经过了多少次).

简单的方法是:您已经有一个事件对象,每个从属进程都已打开,因此您可以使用它。在主进程中设置事件后,关闭句柄,然后轮询,直到发现事件对象不再存在

更好的方法:如前所述,将管道命名为同步对象听起来很复杂,但事实并非如此。

其思想是,每个从属进程在启动时都会创建一个命名管道的实例(即,所有进程都具有相同的名称)。不需要监听线程,甚至根本不需要任何I/O逻辑;您只需要使用创建实例,然后扔掉句柄而不关闭它。当进程退出时,句柄将自动关闭,这就是我们所需要的

要查看是否存在任何从属进程,主进程将尝试使用连接到该命名管道。如果它得到一个“未找到文件”错误,则没有从属进程,因此我们就完成了

如果连接成功,我们至少需要等待一个从属进程。(当您尝试连接到具有多个可用实例的命名管道时,Windows会选择将您连接到哪个实例。它是哪个实例对我们来说并不重要。)

然后主进程将调用(只需一个简单的同步读取,一个字节即可),并等待它失败。一旦您确认错误代码是
错误\u管道破裂
(除非出现严重错误,否则将是),您就知道相关的从属进程已退出。然后,您可以循环并尝试另一个