管道是windows进程通信的一种方式,管道分为匿名管道(anonymous pipe)和命名管道,命名管道主要用于一对多的通信,匿名管道则用于父子进程的通信。匿名管道类似于一根单向的水管,在父子进程间传输字节流。
常用api如下:
创建管道:
BOOL WINAPI CreatePipe(
__out PHANDLE hReadPipe, //管道读取句柄的指针
__out PHANDLE hWritePipe, //管道写入句柄的指针
__in_opt LPSECURITY_ATTRIBUTES lpPipeAttributes, //安全属性,需要设置否则子进程无法访问管道
__in DWORD nSize //缓冲区大小
);
//成功返回非零值,失败返回0
从管道中读取数据:
BOOL WINAPI ReadFile(
__in HANDLE hFile, //文件句柄(管道读取句柄)
__out LPVOID lpBuffer, //缓冲区指针,缓冲区用于存放读取的数据
__in DWORD nNumberOfBytesToRead, //所要读取的最大字节数
__out_opt LPDWORD lpNumberOfBytesRead, //传出参数,记录成功读取的字节数
__inout_opt LPOVERLAPPED lpOverlapped //可选参数,一般填null
);
//成功返回非零值,失败返回0
如果管道中没有数据流,那么readfile会阻塞,所以一般先要判断管道有无数据
//判断管道有无数据,也可用于读数据,但不会清除读过的数据
BOOL WINAPI PeekNamedPipe(
__in HANDLE hNamedPipe, //管道句柄
__out_opt LPVOID lpBuffer, //缓冲区指针(检查有无数据可填NULL)
__in DWORD nBufferSize, //缓冲区大小(检查有无数据可填0)
__out_opt LPDWORD lpBytesRead, //要读取的字节数,不读为NULL
__out_opt LPDWORD lpTotalBytesAvail, //成功读取的字节数(最好要填这个参数不然函数可能失败)
__out_opt LPDWORD lpBytesLeftThisMessage //管道剩余字节?(不读为空)
);
//返回非零值则成功,返回0则失败
向管道写入数据
BOOL WINAPI WriteFile(
__in HANDLE hFile,
__in LPCVOID lpBuffer,
__in DWORD nNumberOfBytesToWrite,
__out_opt LPDWORD lpNumberOfBytesWritten,
__inout_opt LPOVERLAPPED lpOverlapped
);
//参数含义和返回值类似readfile
子进程获得管道句柄:
注意:父子进程使用管道通信时要设置子进程允许继承父进程句柄,否则子进程无法读取管道,此外在调用createprocess创建子进程时,STARTUPINFO结构体需要将管道read句柄设置为标准输入句柄,如图: