gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 14:42:36 24 4
gpt4 key购买 nike

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

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

当使用 fork/wait 将用 C 或 C++ 编写的 linux 应用程序移植到 Windows 时,什么是最合适的 native* 方法来监视父进程中子进程的状态变化(即 WEXITED, WSTOPPED, WCONTINUED ) ?

*native 表示不使用不随 Windows 提供或由 MS 以运行时环境形式直接提供的其他库、框架、程序(如 cygwin、minGW)。

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

//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)

最佳答案

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

根据伪代码,父子之间的信号是 cross-process mutex 的粗略形式。 ,也就是说,他们所做的就是阻止这里的代码:

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

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

此时,父级需要做的就是启动子级并等待它们全部退出。这在 Windows 中很容易通过等待进程句柄来完成。

(我想现代 POSIX 也支持某种比信号更复杂的跨进程互斥锁。)


还值得重新考虑您是否真的需要多个进程。多线程效率会更高,如果代码写得好,适配应该不难。


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

  • 发送信号变成写入单个字节。

  • 在 child 中,等待来自 parent 的信号变成读取单个字节。

  • 在父级中等待来自任何子级的消息有点棘手。它仍然是单字节读取(对于每个 child ),但您需要使用 overlapped I/O而且,如果您需要抚养超过 64 个 child ,IOCP .

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

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

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

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


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

关于c - 最接近 POSIX 等待机制的 Windows 是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34240883/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com