我的程序调用cl.exe并使用管道进行通信。当我试图理解它时,我试图在Windows上使用管道搜索IPC,但找不到太多资源。我发现下面的链接与我的代码有90%相似,但对每个步骤的描述非常少。
http://support.microsoft.com/en-us/kb/190351
有人可以解释一下父母和孩子的关系在这个项目中是如何运作的吗?为什么使用重复句柄?
代码段:
{
HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
HANDLE hInputWriteTmp,hInputRead,hInputWrite;
HANDLE hErrorWrite;
SECURITY_ATTRIBUTES sa;
// Set up the security attributes struct.
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// Create the child output pipe.
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
{
error("Creation of child process output pipe failed");
return false;
}
// Create a duplicate of the output write handle for the std error
// write handle. This is necessary in case the child application
// closes one of its std output handles.
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
{
error("Duplication of child process output pipe failed");
return false;
}
// Create the child input pipe.
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
{
error("Creation of child process input pipe failed");
return false;
}
// Create new output read handle and the input write handles. Set
// the Properties to FALSE. Otherwise, the child inherits the
// properties and, as a result, non-closeable handles to the pipes
// are created.
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
{
error("Creation of child process read handle failed");
return false;
}
if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
GetCurrentProcess(),
&hInputWrite, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
{
error("Creation of child process write handle failed");
return false;
}
// Close inheritable copies of the handles you do not want to be
// inherited.
CloseHandle(hOutputReadTmp);
CloseHandle(hInputWriteTmp);
// Get std input handle so you can close it and force the ReadFile to
// fail when you want the input thread to exit.
HANDLE hStdIn = NULL;
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE )
TRACE("GetStdHandle");
STARTUPINFO Si;
Si.lpDesktop = NULL;
Si.cb = sizeof(Si);
Si.lpReserved = NULL;
Si.lpTitle = NULL;
Si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW | STARTF_USECOUNTCHARS;
Si.dwXCountChars = 10;
Si.dwYCountChars = 8;
Si.wShowWindow = SW_HIDE;
Si.cbReserved2 = 0;
Si.lpReserved2 = NULL;
Si.hStdOutput = hOutputWrite;
Si.hStdInput = hInputRead;
Si.hStdError = hErrorWrite;
PROCESS_INFORMATION Pi;
// Create and start the child process
BOOL processCreated = CreateProcess( NULL,
const_cast<char*>(m_command.c_str()),
NULL,
NULL,
TRUE,
GetCreationFlags(),
NULL,
m_workingDir.c_str(),
&Si,
&Pi);
if (!processCreated)
{
error("Creation of child process failed");
return false;
}
// Close pipe handles (do not continue to modify the parent).
// You need to make sure that no handles to the write end of the
// output pipe are maintained in this process or else the pipe will
// not close when the child process exits and the ReadFile will hang.
CloseHandle(hOutputWrite);
CloseHandle(hInputRead);
CloseHandle(hErrorWrite);
// Read the child's output.
if (!ReadAndHandleOutput(hOutputRead))
{
// Something went wrong so kill and exit
CloseHandle(hOutputRead);
CloseHandle(hInputWrite);
error("Read of compile process result failed");
TerminateProcess(Pi.hProcess, -1);
CloseHandle(Pi.hProcess);
CloseHandle(Pi.hThread);
return false;
}
CloseHandle(hOutputRead);
CloseHandle(hInputWrite);
// Wait for the child process to die
WaitForSingleObject(Pi.hProcess, INFINITE);
if (!GetExitCodeProcess(Pi.hProcess, &m_exitCode))
{
error("Read of child process exit code failed");
CloseHandle(Pi.hProcess);
CloseHandle(Pi.hThread);
return false;
}
CloseHandle(Pi.hProcess);
CloseHandle(Pi.hThread);
}
答案 0 :(得分:0)
CreatePipe - 使用ZwCreateNamedPipe[CreateNamedPipe]
和ZwOpenFile [ CreateFile(OPEN_EXISTING)]
创建命名管道对。
一对实例将在我们的进程中生效(没有没有继承标志),第二个将被复制到子进程(mast有继承标志)。但是我们只有一个公共参数LPSECURITY_ATTRIBUTES
,我们可以设置继承标志。因此,如果设置了此标志,则两个实例都将具有继承的属性。这里可以有几个解决方案。我们无法使用CreatePipe
,但可以直接调用ZwCreateNamedPipe
和ZwOpenFile
来获取正确的继承设置。或者我们可以使用SetHandleInformation
更改继承设置。但是示例的作者选择最差(通过逻辑和效率) - 使用DuplicateHandle
为管道实例创建另一个句柄 - 已经没有继承标志。而不是关闭原始手柄。但是可以使用DUPLICATE_CLOSE_SOURCE
标记来避免下一个CloseHandle
调用 - 惊人的无知。在调用CreateProcess
之后 - 继承的句柄被复制到子进程,我们可以在原始进程中关闭它。所以此时我们有2个管道通道并开始读/写..