与POSIX等待机制最接近的Windows是什么?

时间:2015-12-12 14:21:55

标签: c windows monitoring wait status

Linux支持在" sys / wait.h"中定义的POSIX等待机制。方法wait, waitid, waitpid可用于在使用fork创建的父进程和子进程之间交换状态信息。

Windows既没有为fork提供(本机)支持,也没有提供POSIX等待机制。相反,还有其他方法可用于spwan子进程,即CreateProcess

使用fork / wait向Windows移植使用C或C ++编写的Linux应用程序时,最适合的 native * 方式监视子进程的状态更改(即WEXITED, WSTOPPED, WCONTINUED)父进程?

* native 意味着不使用其他库,框架,程序(如cygwin,minGW),这些库不包含在Windows中,或者由MS以运行时环境的形式直接提供。

编辑:根据评论中的要求,我确实提供了一些关于应该以伪代码形式解决的问题的更多信息:

//creates a new child process that is a copy of the parent (compare 
//POSIX fork()) and returns some sort of handle to it.
function spawnChild() 

// returns TRUE if called from the master process FALSE otherwise
function master()

// return TRUE if called from a child process FALSE otherwise
function child()

// returns TRUE if child process has finished its work entirely, 
// FALSE otherwise.
function completelyFinished()

//sends signal/message "sig" to receive where receiver is a single 
//handle or a set of handles to processes that shall receive sig
function sendSignal(sig, receiver)

// terminates the calling process
function exit()

// returns a handle to the sender of signal "sig"
function senderOf(sig)

function masterprocess()
  master //contains handle to the master process
  children = {}   //this is an empty set of handles to child processes
  buf[SIZE]  //some memory area of SIZE bytes available to master process and all children
  FOR i = 0 TO n - 1
    //spawn new child process and at its handle to the list of running 
    //child processes.
    children <- children UNION spawnChild() 
  IF(master())
    <logic here>
    sendSignal(STARTWORKING, children) //send notification to children
    WHILE(signal = wait())  // wait for any child to respond (wait is blocking) 
      IF signal == IMDONE
        <logic here (involving reads/writes to buf)>
        sendSignal(STARTWORKING, senderOf(signal))
      ELSEIF signal == EXITED
        children <- children \ signal.sender //remove sender from list of children
  ELSEIF(child())
    WHILE(wait() != STARTWORKING);
       <logic here (involving reads/writes to buf)>
       IF completelyFinished()
         sendSignal(EXITED, master)
         exit()
       ELSE
         sendSignal(IMDONE, master)

3 个答案:

答案 0 :(得分:4)

在回答实际问题之前,我将建议一个更好的解决方案:您应该考虑简化父母和孩子之间的关系。

基于伪代码,父母和孩子之间的信号作为cross-process mutex的粗略形式,即他们所做的就是阻止代码:

  IF signal == IMDONE
    <logic here (involving reads/writes to buf)>
    sendSignal(STARTWORKING, senderOf(signal))

同时运行多个实例。相反,应将<logic here>移动到相应的子进程中,由互斥锁保护,以便一次只能运行一个子进程。

此时,所有父母需要做的就是启动孩子并等待他们全部退出。通过等待进程句柄,可以在Windows中轻松完成。

(我认为现代POSIX还支持某种比信号更复杂的跨进程互斥体。)

重新考虑是否真的需要多个流程也是值得的。多线程会更有效,如果代码写得正确,那么应该很难适应它。

尽管如此,如果由于某种原因你绝对必须保留尽可能多的原始程序结构,pipes可能会是你最好的选择。

  • 发送信号会写入一个字节。

  • 在孩子中,等待来自父母的信号会变成单个字节。

  • 在父母那里等待来自任何一个孩子的消息有点麻烦。它仍然是一个单字节读取(对于每个孩子),但您需要使用overlapped I/O,如果您需要支持超过64个孩子,IOCP

(或者,您可以使用多个线程,但这可能涉及太多的结构更改。)

  • 如果管道正确实现,当子项退出或死亡时,父项中的相应读取操作将以ERROR_BROKEN_PIPE错误终止。因此,不需要单独的机制来监测孩子的健康状况。

在这种情况下,我认为anonymous pipes是最合适的选择。这些都是单面的,因此每个孩子都需要两个管道。您可以将子句柄的子句末端作为子进程的标准输入和输出传递。

对于匿名管道,您需要确保在每个子项启动后关闭父句柄的父副本,并且每个子项仅继承与其自己的管道对应的句柄。如果孩子的管道末端有任何额外的手柄处于打开状态,则当孩子退出时,父母将不会收到任何通知。

这一切都不是特别复杂,但要注意命名管道I / O有一点学习曲线。异步I / O更是如此,特别是如果您来自UNIX背景。请特别注意,要使用异步I / O,请发出操作然后等待它完成,而不是等待I / O准备就绪的UNIX模型,然后发出操作。

答案 1 :(得分:2)

如果要向其他进程发出布尔条件信号,可能应该使用共享事件。您可以通过名称或句柄复制来共享它们。你可以随意拥有这些信号。例如,您可以为每个WEXITED, WSTOPPED, WCONTINUED分配一个。

看到你的编辑:事件很棒。在父项中创建命名事件,并将命令上的名称传递给子项。这样父母和孩子就可以互相发出信号。

您还需要共享内存部分,例如通过内存映射文件。这与您代码中的buf相对应。

答案 2 :(得分:2)

你在那里看到的是一个工作队列安排,你有一个生产者进程和一堆工作进程。目前还不清楚您是将共享内存仅用作工作队列,还是您的工作人员正在 on 共享内存(可能是一个巨大的矩阵或向量问题)。

在Win32中,您可能不会将其作为单独的进程实现。

您将使用已经共享内存(相同地址空间)的生产者/消费者线程集合,并使用信号量或条件变量实现工作队列。

实际上,您可能使用更高级别的抽象,例如QueueUserWorkItem。这使用默认的Windows线程池,但您可以使用CreateThreadpool创建自己的线程池。