进程间通信之无名管道

      无名管道,顾名思义,就是没有名字的管道,用于实现父子进程兄弟进程之间的通信。实际上,内核创建无名管道的过程主要就是创建一个匿名文件的过程,内核会分配一个页面用作管道的缓冲区,即管道文件,它并不出现在磁盘或其他文件系统存储介质上,而只存在于内存空间,其他进程也无从访问这个文件。所以,所谓管道文件实质上只是一个用作缓冲区的内存页面,只是把它纳入了文件系统的机制,借用了文件系统的各种数据结构和操作加以管理而已。

无名管道的特点
  • 没有名字
  • 只能用于“近亲”进程
  • 半双工通信
父子之间通信管道的创建
  1. 父进程 A 创建无名管道文件,创建完成时代表着管道两端的两个文件描述符都在 A 中,如下图

                                                   

      2.    父进程 A 通过fork() 创建出子进程 B, fork()时子进程 B 复制父进程 A 的打开文件表,如下图

                                  

      3.  父进程 A 关闭管道的读端,子进程 B 关闭管道的写端,于是,管道的写端在父进程 A 中而读端在子进程 B 中,如下图:

                              

   至此,父进程 A 和子进程 B 就可以通过该管道进行通信了。

兄弟进程之间通信管道的建立

      4.  父进程 A 又通过fork() 创建出子进程 C, 然后父进程 A 关闭写端,与管道脱离关系,使得管道的写端在子进程 C 中而读端在进程 B 中,如下图:

                            

至此,子进程 B 和子进程 C 之间的通信管道就建立了,它们可以通过 exec() 执行自己的目标程序,并通过管道进行单向通信。

无名管道读端和写端特点

读取管道文件时,有两种情况:

(1) 管道文件中无数据

       1) 创建管道时设置了 O_NOBLOCK 标志位,立即返回;

       2) 写端处于关闭状态,返回;

       3) 如果不是以上两种情况,则当前进程进入睡眠,等待写端进程写入数据。

 (2) 管道文件中有数据

       1) 管道中数据长度 >= 要求读出的数据长度,读出要求的数据长度,并返回要求读出的数据长度;

       2) 管道中数据长度 < 要求读出的数据长度, 读出管道中所有数据,并返回实际读出的数据长度。

 注意:在这种情况下,如果有正在等待写的进程,唤醒它,因为读完管道后会腾出一部分空间。

写入管道文件时,有以下四种情况:

     1) 读端处于关闭状态,当前进程给自己发送一个 SIGPIPE 信号,表示管道断裂;

     2) 管道文件已满,当前进程进入睡眠,等待读端读取数据;

     3) 管道文件空闲长度 >= 写入数据长度,直接写入数据;

     4) 管道文件空闲长度 < 写入数据长度,一个字节一个字节写,直到有足够的空间为止。

注意:将数据写入管道文件后,如果有正在睡眠中等待读取数据的进程,则唤醒它。




猜你喜欢

转载自blog.csdn.net/trajectoryofbird/article/details/80802959