在重定向的stdout管道上禁用缓冲(Win32 API,C ++)

时间:2010-08-02 06:14:25

标签: windows winapi redirect stdout

我正在使用CreateProcess从Win32生成一个进程,将hStdOutput的{​​{1}}和hStdError属性设置为使用STARTUPINFO创建的管道句柄。我有两个线程读取管道,等待数据可用(或完成的过程,此时它检查在终止线程之前没有剩余数据)。
随着数据变得可用,我将输出写入有效的大文本框。

正在发生的事情是输出被缓冲,因此缓慢运行的进程只会获取文本框中抛出的数据块,但不会“正常”。

我不确定它是否正在进行缓冲管道,或者与重定向有关。

有没有办法将管道设置为无缓冲,或者以尽快发送stdout的方式启动进程?

我正在使用测试应用程序进行测试,该应用程序会间隔一秒打印行

CreatePipe

4 个答案:

答案 0 :(得分:4)

缓冲可能在C运行时(printf等),你可以做的很少(IIRC它会进行isatty()检查以确定缓冲策略)

答案 1 :(得分:0)

SetNamedPipeHandleState,但它只控制远程管道的缓冲,而不是两端都在同一台计算机上。

答案 2 :(得分:0)

在我看来,如果将hStdOutput hStdError STARTUPINFO 而非设置为使用{{1}创建的管道句柄,则可以解决问题},而不是你创建一个命名管道(CreatePipe功能完全像你之前使用的CallNamedPipe = bInheritHandle使用SECURITY_ATTRIBUTES,请参阅http://msdn.microsoft.com/en-us/library/aa365782.aspx)然后使用TRUE标志在CreateFile方面按名称打开。就像您可以在MSDN上阅读(http://msdn.microsoft.com/en-us/library/aa365592.aspx):

  

管道客户端可以使用CreateFile   通过指定启用重叠模式   FILE_FLAG_OVERLAPPED或启用   通过指定直写模式   FILE_FLAG_WRITE_THROUGH。

因此,只需使用FILE_FLAG_WRITE_THROUGH标志重新打开CreateFile管道,并将句柄/句柄设置为FILE_FLAG_WRITE_THROUGH的{​​{1}}和hStdOutput

答案 3 :(得分:0)

在我的情况下,缓冲是在客户端的输出中(如@Anders 所写),它使用普通的 printf。也许这也取决于 C 运行时(Visual Studio 2019)的实现,也许运行时检测到“不是控制台”并启用缓冲。

所以我通过这个调用禁用了缓冲 setvbuf(stdout, (char*)NULL, _IONBF, 0); 在我的客户端中,现在我立即在服务器的管道中获得输出。

只是为了完整性:这是我在服务器中读取管道的方式

HANDLE in;
CreatePipe(&in, &startup.hStdOutput, &sa, 0);            // Pipe for stdout of the child

...

char buffer[16384];
DWORD read, total;
while (PeekNamedPipe(in, NULL, 0, &read, &total, NULL))
{
    if (total == 0)
    {
        if (WaitForSingleObject(info.hProcess, 0) == WAIT_OBJECT_0)
        {
            if (PeekNamedPipe(in, NULL, 0, &read, &total, NULL) && total == 0)
                break;
            continue;
        }
        Sleep(10);
        continue;
    }

    if (total > sizeof(buffer))
        total = sizeof(buffer);
    ReadFile(in, buffer, total, &read, NULL);

    ...
}