【Linux编程】进程间通信:有名管道(PIPE)、无名管道(FIFO)

进程间的通信:即将一个进程的数据传递给另一个进程。

通信方式:1.管道 2.信号量 3.共享内存 4.消息队列 5.套接字socket(网络通信,不同主机之间的进程)

 

一、什么是管道:

只存在于内存中的文件,对这个文件的操作要通过两个进程进行。

一个进程向管道中写的内容被管道另一端的进程读出。

写入的内容添加在管道缓冲区的末尾;读出要从缓冲区的头部进行。

管道文件:无名管道 有名管道

 

二、进程间通过管道通信方式:半双工通信,即同一时刻,数据流是单向的。

通信方式:

1.单工  2.半双工  3.全双工

三、有名管道(FIFO):

1、类型:

Linux文件系统中的管道文件:

如图:文件类型为p,即管道文件。

管道文件在磁盘上只是一个节点,文件中的数据在内存缓存页面上。

 

2、创建:(2种)

(1)命令行创建:mkfifo myfifo

(2)在程序写代码创建

相应API有:int mkfifo(const char * filename,mode_t mode); //成功返回0,失败返回1.

参数1:const char * filename:路径,即创建后FIFO的名字

参数2:mode_t mode,与open()函数中的mode相同

 

3、FIFO的open打开方式:(4种)

(1)flag = O_RDONLY:open()将会调动阻塞,除非有另一个进程以写的方式打开,否则一直等待

(2)flag = O_WRONLY:open()将会调动阻塞,除非有另一个进程以读的方式打开,否则一直等待

(3)flag = O_RDONLY | O_NONBLOCK:如果此刻没有其他进程以写的方式打开FIFO,此时FIFO也会成功返回,此时FIFO被只读打开,不会返回错误。

(4)O_WRONLY | O_NONBLOCK:立即返回,如果此刻没有其他进程以读的方式打开,open会打开失败,此刻FIFO没有被打开,返回-1。

总结:

4、程序用例:

写入端:mypipe.c (代码分析)

While控制条件:从键盘获取end字符串,则退出,不再往管道中写。

 

读出端:mypipe2.c

While控制条件:从管道中读不到数据时,则退出。

 

分别编译,生成可执行文件read write

5、程序运行结:

6、关闭管道情况:

(1)管道读出端关闭,则写入端会触发异常,写入端也会被系统关闭。

  1. 管道写入端关闭,则读出端read()的返回值为0;

关闭前:

 关闭后:

四、无名管道(pipe):应用于 父子进程间通讯

 

 

1、创建:由pipe()函数创建:int pipe(int pipefd[2]);

参数:pipefd[2],两个id,保存在数组中。pipe()函数会给每一个数组元素赋值。

返回值:成功返回0,失败返回-1.

2、pipe()函数在内核中开辟一块缓冲区(即管道),用于父子进程间通讯。管道有一个读端,一个写端。通过pipefd参数给用户两个文件描述符号。

pipefd[0]指向读端,pipefd[1]指向写端。管道就像一个打开的文件。

通过read(pipefd[0])、write(pipefd[1])向这个管道写数据、读数据。

3、代码分析:

4、运行结果:

五、有名管道 与 无名管道的区别和联系:

1、PIPE和FIFO的区别:

对于FIFO和无名管道的编码区别:

(1)创建并打开一个管道只需调用pipe。创建并打开一个FIFO则需在调用mkfifo后再调用open。

(2)管道在所有进程最终都关闭它之后自动消失。FIFO的名字则只有通过调用unlink才文件系统删除。

FIFO需要额外调用的好处是:FIFO在文件系统中有一个名字,该名字允许某个进程创建个FIFO,与它无亲缘关系的另一个进程来打开这个FIFO。对于管道来说,这是不可能的。

系统规定 :如果写入的数据长度小于等于PIPE_BUF字节,那么或者写入全部字节,要么一个字节都不写入。

在非阻塞的write调用情况下,如果FIFO 不能接收所有写入的数据,将按照下面的规则进行:

 

(1)请求写入的数据的长度大于PIPE_BUF字节,调用失败,数据不能被写入

(2)请求写入的数据的长度小于PIPE_BUF字节,将写入部分数据,返回实际写入的字节数,返回值也可能是0。

其中。PIPE_BUF是FIFO的长度,它在头文件limits.h中被定义。在linux或其他类UNIX系统中,它的值通常是4096字节。注意:PIPE_BUF与FIFO容量是有区别的,PIPE_BUF表示可原子的写往一个管道或FIFO的最大数据量。PIPE_BUF为4096,但是FIFO的容量为65536.

 

2、PIPE和FIFO的相同点:

(1)虽然管道,特别是有名管道可以很方便地在双向上打开读写,但其内核实现依然是单向的。严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。

(2)pipe, fifo都不支持诸如lseek()等文件定位操作。

(3)对于pipe或者fifo,如果在读端或者写端打开了多个读写端(进程),之间的读写是不确定的,需要通过其他的同步机制实现多进程通讯的同步。

猜你喜欢

转载自blog.csdn.net/zDavid_2018/article/details/85643539