简体   繁体   English

在Windows上使用管道的IPC

[英]IPC using Pipes on Windows

My program invokes cl.exe and communicates using pipes. 我的程序调用cl.exe并使用管道进行通信。 When I was trying to understand it, I tried to search about IPC using pipes on windows, but couldn't find much resources. 当我试图理解它时,我尝试使用Windows上的管道搜索IPC,但是找不到太多资源。 I found below link which is 90% similar to my code, but there is very less description about each steps. 我在下面找到了与我的代码90%相似的链接,但是每个步骤的描述都很少。

http://support.microsoft.com/en-us/kb/190351 http://support.microsoft.com/en-us/kb/190351

Can somebody explains me how the parent and child relationship works in this program? 有人可以向我解释一下该程序中父母与子女的关系如何工作吗? why duplicate handle is used? 为什么使用重复的句柄?

Code snippet: 程式码片段:

{
    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);
}

CreatePipe - create named pipes pair by using ZwCreateNamedPipe[CreateNamedPipe] and ZwOpenFile [ CreateFile(OPEN_EXISTING)] . CreatePipe-使用ZwCreateNamedPipe[CreateNamedPipe]ZwOpenFile [ CreateFile(OPEN_EXISTING)]创建命名管道对。

one instance of pair will be live in our process(no not have inherit flag) and second will be duplicated to child process (mast have inherit flag). 对的一个实例将存在于我们的进程中(没有继承标志),第二个将复制到子进程中(主进程具有继承标志)。 however we have only one common parameter LPSECURITY_ATTRIBUTES , where we can set inherit flag. 但是,只有一个公共参数LPSECURITY_ATTRIBUTES ,我们可以在其中设置继承标志。 as a result if this flag is set - both instances will have the inherited property. 结果,如果设置了此标志-两个实例都将具有继承的属性。 here can be several solutions. 这里可以有几种解决方案。 we can not use CreatePipe , but direct call ZwCreateNamedPipe and ZwOpenFile for just correct inherit settings. 我们不能使用CreatePipe ,而是直接调用ZwCreateNamedPipeZwOpenFile来获取正确的继承设置。 or we can change inherit settings by using SetHandleInformation . 或者我们可以使用SetHandleInformation更改继承设置。 but author of example select worst (by logic and efficiency) - use DuplicateHandle for create another handle for pipe instance - already without inherit flag. 但是示例的作者选择了最糟糕的方法(根据逻辑和效率)-使用DuplicateHandle为管道实例创建另一个句柄-已经没有继承标志。 and than close original handle. 然后关闭原始手柄。 however can be used DUPLICATE_CLOSE_SOURCE flag for avoid next CloseHandle call - stunning ignorance. 但是,可以使用DUPLICATE_CLOSE_SOURCE标志来避免下一次CloseHandle调用-令人震惊的无知。 after call CreateProcess - inherited handles is duplicated to child process, and we can close it in original process. 调用CreateProcess -继承的句柄将复制到子进程,我们可以在原始进程中将其关闭。 so at this point we have 2 pipe channels and begin read/write.. 因此,在这一点上,我们有2个管道通道并开始读/写。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM