相当于在Windows上选择管道

时间:2016-07-09 00:39:57

标签: c++ winapi pipe

我需要阻止,直到我的一个管道中有数据被读取。

我已经尝试过WaitForMultipleObjects,但它只是立即返回说其中一个管道有数据。管道块上的后续ReadFile。

我无法使用PeekNamedPipe,因为我需要阻止直到数据可用,并且在睡眠循环中偷看会因睡眠而导致延迟反应。

这段代码是跨平台的,一切都在linux上运行得很好,因为我可以在一组fifo fd' s上使用Select,然后在select返回时从那个就读的那个读取,但是没有似乎在Windows上是等效的。

我见过很多人说你必须使用带有读/写的重叠操作,但是这不会要求我循环并尝试读取每一个管道吗?

是否有一个阻塞操作阻塞,直到其中一个管道中有数据?

2 个答案:

答案 0 :(得分:2)

  

我已经尝试过WaitForMultipleObjects,但它只是立即返回说其中一个管道有数据。管道块上的后续ReadFile。

MSDN的可等待对象类型列表中未提及管道,因此您无法将管道传递给任何WaitFor...()系列函数。

  

我见过很多人说你必须使用带有读/写的重叠操作,但是这不会要求我循环并尝试读取每一个管道吗?

重叠的I / O是解决您问题的方法。

以重叠模式创建管道。然后你可以:

  1. 通过CreateEvent()创建一个事件对象,并将其分配给您用于给定读取操作的OVERLAPPED结构。然后,您可以在多个管道上发出异步ReadFile/Ex()操作,并使用WaitForMultipleObject()等待事件对象,直到其中一个发出信号。 WaitForMultipleObjects()的返回值将告诉您哪个事件已发出信号,并通过关联哪个管道已读取某些数据。

  2. 使用GetQueuedCompletionStatus/Ex()代替WaitForMultipleObjects(),然后您可以省略事件对象。 GetQueuedCompletionStatus/Ex()会告诉您哪些特定的OVERLAPPED结构已经完成(如果需要,您可以使用hEvent字段传递用户定义的数据。)

    < / LI>

    MSDN文档中对此进行了介绍:

    Synchronous and Overlapped Pipe I/O

    select()可以在一次通话中报告多个已完成的操作。但是,WaitForMultipleObjects()GetQueuedCompletionStatus()一次只能报告一个已完成的操作。您必须在循环中调用它们以发现是否已完成多个操作。另一方面,GetQueuedCompletionStatusEx()可以一次报告多个已完成的操作。

      

    是否有一个阻塞操作阻塞,直到其中一个管道中有数据?

    是。见上文。

答案 1 :(得分:-1)

是的,使用重叠I / O是最佳选择。您可以将每个管道句柄绑定到I / O完成端口(直接通过CreateIoCompletionPort(),或间接通过BindIoCompletionCallback())。对于异步读取,创建一个继承自OVERLAPPED的结构,并使用管道句柄将其传递给ReadFile/Ex()。每次读取都需要自己分配的该结构实例。然后,您可以使用GetQueuedCompletionStatus()(或绑定回调)来检测每次读取的完成时间。你不需要任何循环。