[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; }