C++ 子进程上的ReadFileEx重叠';重定向的STDOUT从不开火
我有一个长期运行的基于控制台的应用程序发送器,它使用非缓冲输出(如cout)将简单文本发送到标准输出。我认为您有一个输入错误:C++ 子进程上的ReadFileEx重叠';重定向的STDOUT从不开火,c++,windows,redirect,C++,Windows,Redirect,我有一个长期运行的基于控制台的应用程序发送器,它使用非缓冲输出(如cout)将简单文本发送到标准输出。我认为您有一个输入错误: CreatePipe(&handles[h_Child_StdOut_Read], &handles[h_Child_StdOut_Write], &sa, 0); SetHandleInformation(handles[h_Child_StdOut_Read], HANDLE_FLAG_INHERIT, 0); CreatePipe(&handles[h_Child
CreatePipe(&handles[h_Child_StdOut_Read], &handles[h_Child_StdOut_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdOut_Read], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&handles[h_Child_StdIn_Read], &handles[h_Child_StdIn_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdIn_Read], HANDLE_FLAG_INHERIT, 0);
将最后一个更改为
SetHandleInformation(handles[h_Child_StdIn_Write], HANDLE_FLAG_INHERIT, 0);
这也是他们在MSDN示例中所做的。除了@DyP指出的错误之外,您还假设
CreatePipe
以重叠模式打开句柄您的假设不正确。微软:
不支持异步(重叠)读写操作
通过匿名管道。这意味着您不能使用ReadFileEx和
具有匿名管道的WriteFilex函数。此外,
读取文件和写入文件的lpOverlapped参数在以下情况下被忽略:
函数与匿名管道一起使用
(事实上,如果您查看kernel32.dll
,例如在Windows XP上,CreatePipe
没有将第七个参数的低位设置为NtCreateNamedPipeFile
;该位是在调用CreateNamedPipe
时设置的,FILE\u FLAG\u重叠
)
寻找Dave Hart的实施方案;当需要重叠I/O时,它可以作为
CreatePipe
的插入式替代品。只需将PipeSerialNumber++
更改为InterlockedIncrement(&PipeSerialNumber)
即可避免MT代码中的争用条件。这是如何编译的?ReadFileEx()的第四个参数是重叠的*,而不是IO*,不管它是什么。@Hans:IO
是从“重叠”派生的。我已经在上面添加了声明。事实上,我很久以前就知道了这一点,但你的回答将对未来的访问者有所帮助。
vector<HANDLE> wait_handles;
wait_handles.push_back(handles[h_Die_Sig]);
wait_handles.push_back(handles[h_Child_Process]);
for( bool cont = true; cont; )
{
IO* io = new IO;
memset(io, 0, sizeof(IO));
io->buf_size_ = 16 * 1024;
io->buf_ = new char[io->buf_size_];
memset(io->buf_, 0, io->buf_size_);
io->thread_ = ¶m;
io->file_ = handles[h_Child_StdOut_Read];
if( !ReadFileEx(io->file_, io->buf_, io->buf_size_, io, OnFileRead) )
{
DWORD err = GetLastError();
string err_msg = util::strprintwinerr(err);
}
DWORD rc = WaitForMultipleObjectsEx(wait_handles.size(), &wait_handles[0], FALSE, INFINITE, TRUE);
// ...
}
struct IO : public OVERLAPPED
{
char* buf_;
DWORD buf_size_;
DWORD read_;
ThreadParam* thread_;
HANDLE file_;
};
void CALLBACK OnFileRead(DWORD err, DWORD bytes, OVERLAPPED* ovr)
{
IO* io = static_cast<IO*>(ovr);
string msg(io->buf_, bytes);
}
CreatePipe(&handles[h_Child_StdOut_Read], &handles[h_Child_StdOut_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdOut_Read], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&handles[h_Child_StdIn_Read], &handles[h_Child_StdIn_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdIn_Read], HANDLE_FLAG_INHERIT, 0);
SetHandleInformation(handles[h_Child_StdIn_Write], HANDLE_FLAG_INHERIT, 0);