参考于原文 https://blog.csdn.net/dacxu/article/details/30071081
然后我亲自在windows下手敲了一遍并做了一些注释
我的理解:
windows的匿名管道 在于 父进程和子进程之间创建,需要创建两个管道,一共四个HANDLE,还需要关掉两个
设父进程到子进程的管道为pipein,连接父进程的一端,HANDLE为wt,连接子进程的一端,HANDLE为rd
设子进程到父进程的管道为pipeout,连接父进程的一端,HANDLE为rd,连接子进程的一端,HANDLE为wt
父进程代码解析:
#include "stdafx.h"
#include <string>
#include <iostream>
#include <Windows.h>
int main(int argc, char **argv)
{
//创建两个管道需要的4个句柄
HANDLE hpipeInRd, hpipeInWt;
HANDLE hpipeOutRd, hpipeOutWt;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = FALSE;
if (!CreatePipe(&hpipeOutRd, &hpipeOutWt, &sa, 0))
{
printf("stdout Create Pipe error!!!");
return 1;
}
//将hpipeOutRd关闭
if(!SetHandleInformation(hpipeOutRd, HANDLE_FLAG_INHERIT, 0))
{
printf("stdout SetHandleInformation !!!");
return 1;
}
if (!CreatePipe(&hpipeInRd, &hpipeInWt, &sa, 0))
{
printf("stdin Create Pipe error!!!");
return 1;
}
//将hpipeInWt关闭
if (!SetHandleInformation(hpipeInWt, HANDLE_FLAG_INHERIT, 0))
{
printf("stdout SetHandleInformation !!!");
return 1;
}
//创建子进程
TCHAR lpCommandLine[100] = _T("client");
PROCESS_INFORMATION pi;//pi 获取子进程的信息
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdError = hpipeOutWt;
si.hStdOutput = hpipeOutWt; //将子进程的标准输出重定向到pipeout管道的写段
si.hStdInput = hpipeInRd; //将子进程的标准输入重定向到pipein管道的读端
si.dwFlags |= STARTF_USESTDHANDLES;
//CREATE_NEW_CONSOLE:子进程将打开一个新的命令行终端
int ret = CreateProcess(NULL, lpCommandLine, NULL, NULL,
TRUE, 0/*CREATE_NEW_CONSOLE*/, NULL, NULL, &si, &pi);
if (ret)
{
//此处我暂时没办法知道子进程什么时候打开
//WaitForSingleObject函数用来检测hHandle事件的信号状态,
//在某一线程中调用该函数时,线程暂时挂起,如果在挂起的
//dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,
//则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,
//但hHandle所指向的对象还没有变成有信号状态,函数照样返回。
//如果将参数设置为INFINITE, 子线程由于标准输入和标准输出被重定向
//所以在控制台无法进行人为的输入和输出,父进程无法得到子进程的信号
//也一直阻塞在那里
WaitForSingleObject(pi.hProcess, 2);
printf("child process is created!!!\n");
//在父进程中不需要子进程的一些东西,
//所以将子进程句柄和子进程的线程句柄关闭
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
//父进程中标准输入,以下有这几种写法
char buffer[100] = {0};
DWORD read;
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
ReadFile(hstdin, buffer, sizeof(buffer), &read, NULL);
//fgets(buffer, sizeof(buffer), stdin);
//std::cin >> buffer;
//scanf_s("%s",buffer, sizeof(buffer));
//父进程将从控制台获得的数据写到pipein管道的写端
DWORD writeBytes;
WriteFile(hpipeInWt, buffer, strlen(buffer), &writeBytes, NULL);
//父进程从pipeout的读端读取数据
DWORD readBytes;
memset(buffer, 0, sizeof(buffer));
ReadFile(hpipeOutRd, buffer, sizeof(buffer), &readBytes, NULL);
printf("msg from child process is: %s\n", buffer);
//关闭句柄
CloseHandle(hpipeInRd);
CloseHandle(hpipeInWt);
CloseHandle(hpipeOutWt);
CloseHandle(hpipeOutRd);
return 0;
}
子进程代码 参见
https://blog.csdn.net/dacxu/article/details/30071081