匿名管道
BOOL WINAPI CreatePipe(
_Out_PHANDLE hReadPipe, 返回一个可用于读管道数据的文件句柄
_Out_PHANDLE hWritePipe, 返回一个可用于写管道数据的文件句柄
_In_opt_LPSECURITY_ATTRIBUTES lpPipeAttributes,
传入一个SECURITY_ATTRIBUTES结构的指针,该结构用于决定该函数返回的句柄是否可被子进程继承。
_In_DWORD nSize);
管道的缓冲区大小。但是这仅仅只是一个理想值,系统根据这个值创建大小相近的缓冲区。如果传入0 ,那么系统将使用一个默认的缓冲区大小。
匿名管道用于进程之间通信,且仅限于本地父子进程之间通信,结构简单,类似于一根非水平状态的水管,一端进水另一端出水(单工)。在本地机器上可以使用匿名管道来实现父进程和子进程之间的通信。
管道是IPC最基本的一种实现机制。我们都知道在Linux下“一切皆文件”,其实这里的管道就是一个文件。管道实现进程通信就是让两个进程都能访问该文件。
匿名管道的特征:
①只提供单向通信,也就是说,两个进程都能访问这个文件,假设进程1往文件内写东西,那么进程2 就只能读取文件的内容。
②只能用于具有血缘关系的进程间通信,通常用于父子进程建通信
③管道是基于字节流来通信的
④依赖于文件系统,它的生命周期随进程的结束结束(随进程)
⑤其本身自带同步互斥效果
匿名管道主要用于本地父进程和子进程之间的通信,在父进程中的话,
首先是要创建一个匿名管道,
在创建匿名管道成功后,可以获取到对这个匿名管道的读写句柄,
然后父进程就可以向这个匿名管道中写入数据和读取数据了、
但是如果要实现的是父子进程通信的话,那么还必须在父进程中创建一个子进程,
同时,这个子进程必须能够继承和使用父进程的一些公开的句柄。
为什么呢?
因为在子进程中必须要使用父进程创建的匿名管道的读写句柄,通过这个匿名管道才能实现父子进程的通信,所以必须继承父进程的公开句柄。
同时在创建子进程的时候,必须将子进程的标准输入句柄设置为父进程中创建匿名管道时得到的读管道句柄,将子进程的标准输出句柄设置为父进程中创建匿名管道时得到的写管道句柄。
然后在子进程就可以读写匿名管道了
使用管道需要注意的4种特殊情况:
如果所有指向管道写端的文件描述符都关闭了,而仍然有进程从管道的读端读数据,那么文件内的所有内容被读完后再次read就会返回0,就像读到文件结尾。
如果有指向管道写端的文件描述符没有关闭(管道写段的引用计数大于0),而持有管道写端的进程没有向管道内写入数据,假如这时有进程从管道读端读数据,那么读完管道内剩余的数据后就会阻塞等待,直到有数据可读才读取数据并返回。
如果所有指向管道读端的文件描述符都关闭,此时有进程通过写端文件描述符向管道内写数据时,则该进程就会收到SIGPIPE信号,并异常终止。
如果有指向管道读端的文件描述符没有关闭(管道读端的引用计数大于0),而持有管道读端的进程没有从管道内读数据,假如此时有进程通过管道写段写数据,那么管道被写满后就会被阻塞,直到管道内有空位置后才写入数据并返回。
首先创建两个管道
HANDLE m_hReadParent;
HANDLE m_hWriteChild;
BOOL bRet = CreatePipe(
&m_hReadParent, //读出端句柄
&m_hWriteChild, //写入端句柄
&sa,
0); //使用默认的缓冲区大小
HANDLE m_hWritePrent;
HANDLE m_hReadChild;
bRet = CreatePipe(
&m_hReadChild, //读出端句柄
&m_hWritePrent, //写入端句柄
&sa,
0); //使用默认的缓冲区大小