进程间通信:管道及命名管道(代码实现)

六月ゝ 毕业季﹏ 提交于 2019-11-29 22:12:15

管道:1.管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;

            2.只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

            3.单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,                  并且只存在与内存中;

            4.数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据;

            5.管道通信是于流式符的;

            6.管道的生命周期是随进程的;

            7.管道已经给进程提供了同步与互斥;



pipe:


 当一个管道建立时,它会创建两个文件描述符pipefd[0]和pipefd[1]。其中pipefd[0]固定用于读管道,而pipefd[1]固定用于写管道,一般文件I/O的函数都可以用来操作管道。


测试pipe的大小


      单独创建一个无名管道,并没有实际的意义。我们一般是在一个进程在由pipe()创建管道后,一般再由fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。

代码:





结果:


使用管道需要注意以下4中情况:

1.如果所有指向管道写端的文件描述符没关闭,而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中深剩余的数据都被读取后,再次read

   会阻塞,直到管道中有数据可读了才读取数据并返回。




结果:



2.如果所有指向管道写端的文件描述符都关闭了,而仍然有进程从管道的读端读数据,那么管道中深剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。




结果:


3.如果所有指向管道读端的文件描述符没关闭,而持有管道读端的进程也没有从管道中读数据,这时有进程从管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道

   中有空位置了才写入数据并返回。


4.如果所有指向管道读端的文件描述符都关闭了,这时有进程从管道的写端写数据,那么该进程会收到信号SIGPIPE,通常会导致进程遗产法终止。





结果:


命名管道:FIFO不同于无名管道之处在于它提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中,这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信,因此,通过FIFO不相关的进程也能交换数据。值的注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。

Linux下有两种方式创建命名管道。一是Shell下交互地建立一个命名管道,二是在程序中使用系统函数建立命名管道。Shell方式下可使用mknod或mkfifo命令:

#include<sys/types.h>

#include<sys/stat.h>

int mknod(const char *path,mode_t mod,dev_t dev);

int mkfifo(const char *path,mode_t mode);

       函数mknod参数中path为创建的命名管道的全路径名:mod为创建的命名管道的模式,指明其存取权限;dev为设备值,该值取决于文件创建的种类,它只在创建设备文件

时才会用到。这两个函数调用成功都返回0,失败都返回-1.

read:



write:



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!