【问题标题】:in windows, how to have non-blocking stdin that is a redirected pipe?在 Windows 中,如何拥有作为重定向管道的非阻塞标准输入?
【发布时间】:2010-10-26 14:11:00
【问题描述】:

我有一个 Windows C 程序,它通过重定向的 stdin 管道获取其数据,有点像这样:

./some-data-generator | ./myprogram

问题是我需要能够以非阻塞方式读取stdin。这样做的原因是(1)输入是数据流并且没有EOF 和(2)程序需要能够随时中止其stdin-读取线程。 fread 在没有数据时阻塞,所以这很困难。

在 Unix 中这没有问题,因为您可以使用 fcntlO_NONBLOCK 设置文件描述符的阻塞模式。但是,fcntl 在 Windows 上不存在。

我尝试使用SetNamedPipeHandleState

    DWORD mode= PIPE_READMODE_BYTE|PIPE_NOWAIT;
    BOOL ok= SetNamedPipeHandleState(GetStdHandle(STD_INPUT_HANDLE), &mode, NULL, NULL);
    DWORD err= GetLastError();

但这会因ERROR_ACCESS_DENIED (0x5) 而失败。

我不知道还能做什么。这实际上是不可能的(!)还是只是高度模糊?对于这个特定的问题,网络上的资源相当稀少。

【问题讨论】:

    标签: c++ c windows stdin pipe


    【解决方案1】:

    订单方法,检查是否有可供读取的输入:

    • 对于控制台模式,您可以使用 GetNumberOfConsoleInputEvents()。
    • 对于管道重定向,您可以使用 PeekNamedPipe()

    【讨论】:

    • PeekNamedPipe 是我一直在寻找的... 这允许您随后调用 ReadFile 以便它不会阻塞。
    【解决方案2】:

    您可以使用异步 I/O 从句柄中读取,例如 ReadFileEx() WIN32 调用。使用 CancelIo() 在没有输入的情况下终止读取。

    请参阅 MSDN http://msdn.microsoft.com/en-us/library/aa365468(VS.85).aspx

    【讨论】:

    • 如果句柄是匿名管道,那将不起作用 - 因为它将在问题中给出的示例中。匿名管道无法实现重叠(异步)I/O。
    猜你喜欢
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 2016-04-26
    相关资源
    最近更新 更多