[Windows进程间通信] 匿名管道

参考链接: https://blog.csdn.net/weixin_41875267/article/details/108466758

通过匿名管道可以实现两个进程间的数据传输。

使用管道的缺点:

1. 只能用于有父子关系的进程,且管道可能遇到阻塞问题

2. 只能用于本地的进程间通信,不能跨机器

主要用到的API

BOOL CreatePipe(
  [out]          PHANDLE               hReadPipe,
  [out]          PHANDLE               hWritePipe,
  [in, optional] LPSECURITY_ATTRIBUTES lpPipeAttributes,
  [in]           DWORD                 nSize
);

BOOL ReadFile(
  [in]                HANDLE       hFile,
  [out]               LPVOID       lpBuffer,
  [in]                DWORD        nNumberOfBytesToRead,
  [out, optional]     LPDWORD      lpNumberOfBytesRead,
  [in, out, optional] LPOVERLAPPED lpOverlapped
);

BOOL WriteFile(
  [in]                HANDLE       hFile,
  [in]                LPCVOID      lpBuffer,
  [in]                DWORD        nNumberOfBytesToWrite,
  [out, optional]     LPDWORD      lpNumberOfBytesWritten,
  [in, out, optional] LPOVERLAPPED lpOverlapped
);

使用匿名管道时,先用CreatePipe创建管道,管道有一个读句柄和一个写句柄。随后可以创建子进程,通过修改子进程的标准输入输出实现与子进程的通信。如父进程通过写句柄写入数据,子进程通过读句柄读取数据。常见的情况是创建2个管道,一个用于父进程向子进程写入,一个用于子进程向父进程写入。

以下是示例:

父进程创建子进程并向子进程写数据,子进程读取到数据后,将内容再输出到父进程的窗口上

父进程:

#include <windows.h>
#include <iostream>
using namespace std;

HANDLE hRead;
HANDLE hWrite;

BOOL CreateChildProcess() {
    SECURITY_ATTRIBUTES sa;
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    if (!CreatePipe(&hRead, &hWrite, &sa, 0)) {
        printf("Failed to create pipe.");
        return FALSE;
    }

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput = hRead; // Child process read from this handle rather than std input handle
    si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); // Child process also outputs content to parent's window
    if (FALSE == CreateProcess("child.exe",
        NULL, 
        NULL, 
        NULL, 
        TRUE, 
        0, 
        NULL, 
        NULL, 
        &si, 
        &pi)) {
        auto err = GetLastError();
        CloseHandle(hRead);
        CloseHandle(hWrite);
        return FALSE;
    }
    else {
        
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    return TRUE;
}

#define BUFFER_SIZE 4096
void SendData() {
    char data[BUFFER_SIZE] = { 0 };
    while (true) {
        scanf_s("%s", data, BUFFER_SIZE);
        DWORD dwWrite = 0;

        if (!WriteFile(hWrite, data, strnlen_s(data, BUFFER_SIZE) + 1, &dwWrite, NULL)) {
            printf_s("Failed to write to child process.");
        }

        if (strcmp(data, "quit") == 0) {
            break;
        }
    }

}

int main() {
    if (CreateChildProcess()) {
        SendData();
    }
    return 0;
}

 

子进程:

#include <windows.h>
#include <iostream>
using namespace std;

#define BUFFER_SIZE 4096
int main() {
    auto hRead = GetStdHandle(STD_INPUT_HANDLE); // This has been replaed by pipe read handle
    char data[BUFFER_SIZE] = { 0 };
    DWORD dwRead = 0;
    while (true) {
        ReadFile(hRead, data, BUFFER_SIZE, &dwRead, NULL);
        if (strcmp(data, "quit") == 0) {
            break;
        }

        printf_s("child process: %s", data);
    }

    return 0;
}

 

posted @ 2022-05-19 10:06  czhao4  阅读(291)  评论(0编辑  收藏  举报