【Linux】Linux进程间通信之管道

管道介绍:

1、首先来介绍一下什么是管道?

管道是Unix中最古老的进程间通信的形式。我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”,我们可以将这个概念形象的理解为一个我们生活中常见的一些管道,自来水管道,石油管道,天然气管道等等。这些管道有什么共性呢?它们都可以把资源从一端传到另一端,因为不论是石油,自来水,石油都可以称之为资源。

而在计算机中的资源就是数据流。


2、管道的分类:


(1)匿名管道

【1】首先来介绍下匿名管道所需要的函数:

函数原型为:

#include <unistd.h>

int pipe(int fd[2]);

功能:创建一无名管道原型

参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端

返回值:成功返回0,失败返回错误代码

先简单实现一个匿名管道:



运行结果如下:


这份代码的功能呢就是,从键盘输入字符然后输出到屏幕上。

代码的基本流程是先创建一个匿名管道文件,从标准输入读入数据到缓冲区中,然后将缓冲区中的数据写入匿名管道文件的写端,这时缓冲区已经不起作用了,为了避免对以后的操作产生影响,顺便将缓冲区中的数据初始化,然后将匿名管道文件的内容读到缓冲区中,再将缓冲区中的内容写到标准输出上,这时就可以利用匿名管道将键盘输入打印到屏幕上。

根据以前所学知识,描述进程的结构体PCB(Lunix下是task_struct)中包含有与文件相关的指针(*file)指向文件列表,列表内都是与该进程相关的文件指针(file*),这个列表就是一段连续的空间,0,1,2分别表示标准输入,标准输出和标准出错,后面的文件依次标号,进程对创建的管道文件进行操作时,有一个读端,有一个写端,进程对文件进行操作时从写端进行写操作,从读端进行读操作。

【2】匿名管道读写规则:
当没有数据可读时
O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
当管道满的时候
O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
如果所有管道写端对应的文件描述符被关闭,则read返回0
如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
【3】匿名管道特点:
只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。管道提供流式服务一般而言,进程退出,管道释放,所以管道的生命周期随进程一般而言,内核会对管道操作进行同步与互斥管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道 


(2)命名管道

【1】命名管道引入

匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文件,可以实现没有亲缘关系的进程之间的数据交换。

【2】命名管道创建

命名管道可以从命令行上创建,命令行方法是使用下面这个命令:


在图中可以看到黑色底色的fifo文件就是我们创建的名为“fifo”的命名管道。

除了直接用命令创建以外,还可以在程序中用函数来创建,函数原型:

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

参数:

参数1表示创建文件的名字,参数2代表创建的文件的参数设置。

返回值:

创建成功返回0,创建失败返回-1

匿名管道与命名管道的区别
匿名管道由pipe函数创建并打开。命名管道由mkfifo函数创建,打开用open

FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。
命名管道的打开规则 命名管道的打开规则
如果当前打开操作是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
O_NONBLOCK enable:立刻返回成功
如果当前打开操作是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

来举个例子来用这个函数真正实现两个无亲缘关系进程之间的通信:

先看代码:

server.c


client.c


分析代码可知代码实现得是,server.c先创建命名管道“mypipe”然后等待client.c将数据输入到管道中,然后server.c将管道中的内容读出来。由于server.c 和client.c分别是一个代码所以它们两个中间不存在亲缘关系,这样就实现了不具有前缘关系的两个进程之间的数据交换。

运行结果:


以上就是管道的所有内容。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值