C Win32,从管道块读取文件,即使在子级终止后

C Win32,从管道块读取文件,即使在子级终止后,c,pipe,win32-process,C,Pipe,Win32 Process,我有一个简单的程序(用C语言编写),它创建两个子进程,分别等待一个继承的管道,并将输出放在一个文件中 除了在两个管道上进行一些写/读循环之后,当子管道结束时,对ReadFile的调用将被阻塞,等待管道上的数据外,其他一切都正常工作。我使用以下模式: ... //create pipe1 CreatePipe(&hReadDup,&hWrite,&saAttr,0); DuplicateHandle(GetCurrentProcess(),hReadDup,GetCurre

我有一个简单的程序(用C语言编写),它创建两个子进程,分别等待一个继承的管道,并将输出放在一个文件中

除了在两个管道上进行一些写/读循环之后,当子管道结束时,对ReadFile的调用将被阻塞,等待管道上的数据外,其他一切都正常工作。我使用以下模式:

...
//create pipe1
CreatePipe(&hReadDup,&hWrite,&saAttr,0);
DuplicateHandle(GetCurrentProcess(),hReadDup,GetCurrentProcess(),&hRead,0,FALSE,DUPLICATE_SAME_ACCESS);
CloseHandle(hReadDup);


si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hWrite;   

CreateProcess(  NULL,
        const_cast<LPWSTR>(cmd2.c_str()), //the command to execute
        NULL,
        NULL,
        TRUE,
        0,
        NULL,
        NULL,
        &si, //si.
        &pi
    );

...
CloseHandle(hWrite); // EDIT: this was the operation not properly done!

while(cont){
    ...
    cont = ReadFile(hRead,buf,50, &actual,NULL);
    ...
}
... 
。。。
//创建管道1
CreatePipe(&hReadDup,&hWrite,&saAttr,0);
DuplicateHandle(GetCurrentProcess(),hReadDup,GetCurrentProcess(),&hRead,0,FALSE,重复\u相同\u访问);
CloseHandle(hReadDup);
si.cb=sizeof(si);
si.dwFlags=STARTF_USESTDHANDLES;
si.hStdOutput=hWrite;
CreateProcess(空,
const_cast(cmd2.c_str()),//要执行的命令
无效的
无效的
是的,
0,
无效的
无效的
&是,//是。
&圆周率
);
...
闭合手柄(hWrite);//编辑:这是未正确完成的操作!
while(续){
...
cont=ReadFile(hRead,buf,50,&actual,NULL);
...
}
... 
最后一次调用(在子进程退出后)块。
了解原因(如果没有,如何调试)?

您正在同步模式下调用
ReadFile()
。只要管道处于打开状态,
ReadFile()
将阻止等待更多数据。如果将
CreateProcess()
返回给您的进程和线程句柄保持打开状态,则会阻止子进程完全退出,因此子端的管道可能不会关闭。在进入读取循环之前,关闭
CreateProcess()
返回的句柄,当子进程完全终止时允许管道正确关闭,然后
ReadFile()
可以在无法从管道读取时向您报告错误。或者,切换到管道上的重叠I/O,以便在循环运行时可以使用
WaitForSingleObject()
GetExitCodeProcess()
监视子进程,以便无论管道状态如何,都可以检测子进程何时终止。

我自己找到了解决方案(这实际上是一个编码错误)。 我没有正确关闭管道的父级写入句柄(
hWrite
),因此同步读取文件无法向我报告子进程终止


如果有人有相同的问题,请确保在对该管道开始I/O操作之前关闭该管道的可继承句柄(如MSDN报告所述,无法再次找到)。在您的情况下,一切正常,您可以访问管道上的两个进程。但是,如果您没有,或者只是想中断
ReadFile
调用,那么
CancelSynchronousIo
就是您的朋友:

实际上,我不能等待子进程在循环终止之前终止。此外,我自己解决了这个问题:我没有正确关闭管道的父级写入句柄,因此同步
ReadFile
无法向我报告子进程终止。非常感谢。anyway@Remy,你确定吗?我从来没有听说过保持进程的打开句柄会阻止Windows在该进程退出时关闭该进程的句柄。我有同样的问题和相同的解决方案——我怀疑这是因为,如果不关闭句柄,父进程可能会写入管道,然后从同一管道本身读取。因此,ReadFile必须等待/管道必须保持打开状态,因为上述(愚蠢的)情况仍然可能发生。但是如果不再存在句柄,那么就再也无法向管道写入任何内容了。关于这个问题的一些有用文档:谢谢您的回答。微软自己的代码示例[1]已被破坏,但这为我解决了问题。[1] :谢谢你的提问和回答。我一直在_popen(…)变体(在我的Code::Blocks GCC环境中工作得很好,但在我的工作环境中根本不工作)和您使用的CreateProcess/CreatePipe方法之间来回跳跃。您的实现非常有效。谢谢,谢谢,今天碰到这个!