匿名管道用于进程之间通信,且仅限于本地父子进程之间通信,结构简单,类似于一根水管,一端进水另一端出水(单工)。相对于命名管道,其占用小实现简单,在特定情况下,比如实现两围棋引擎本地对战可以使用匿名管道。
怎样实现匿名管道双向通信?
由于匿名管道是单工的,所以为实现父子进程双向通信需要创建两根管道,并由子进程继承一根管道的读句柄和另一根管道的写句柄。
如何理解匿名管道的双向通信?
管道相当于一段内存,一个进程输入,一个进程读出。
在进程通信时一般会产生进程同步问题(进程同步讲解请见操作系统类书籍):父子进程各自均具有读写功能,在管道为空时,相应读进程应该被阻塞起来,直到管道被写入为止才被唤醒。
这种空管道不允许读的特性应当加一个锁,但匿名管道自带了这种功能,所以不需要对读写进行限制,其能自动阻塞。
在VS2017下实现匿名管道
对几个基本点进行介绍
#include <windows.h>
匿名管道需要包含此头文件
首先我们需要了解一下最后程序实现中我想要的效果:父进程输入任意长数字(当然局限于匿名管道的最大大小4MB)通过匿名管道传给子进程,由子进程对该字符串(由于在管道中以字符流形式存在)的各位数进行加和,把这个加和的结果返回父进程。
在实际制作时,我将子进程这个计算函数做成动态链接库的形式进行链入。所以在实际代码中将以一行代码的形式呈现:
int Bitadd(char *ary1, char *ary2, unsigned long len, int Lcount);
其中ary1为子进程接收到的字符串、ary2为计算结果、len是接收到的字符串长度、Lcount为计算结果长度。
创建管道
函数原型:
BOOL WINAPI CreatePipe(
_Out_PHANDLE hReadPipe,
_Out_PHANDLE hWritePipe,
_In_opt_LPSECURITY_ATTRIBUTES lpPipeAttributes,
_In_DWORD nSize);
实际调用形式:
CreatePipe(&read, &write, &sa, 0);
其中read是读句柄,write是写句柄,sa是管道安全属性,0代表管道缓冲设置为系统默认值。
由上函数可知在创建管道之前,需要先设置管道安全属性。
设置管道安全属性
对象原型:
typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; //结构体的大小,可用SIZEOF取