【Linux】进程间通信之管道的理解和使用

为什么需要进程间通信?
由于进程都拥有独立的虚拟地址空间,从而导致了进程之间的独立性,通过进程间通信可以使各个进程之间很好的交互或进程控制。

网络是目前最大的进程间通信。

匿名管道

本质上就是在内核中开辟的一块空间,也被称为缓冲区,但是这块空间是没有标识符的。

匿名管道的创建

int pipe(int fd[2])

fd[2]是文件描述符数组,fd[0]代表从管道中读取数据,fd[1]代码往管道中写入数据。成功返回0,失败返回-1。

即:
在这里插入图片描述
数据的流向是从fd[1]->管道->fd[0],且数据只能从中读一次,数据就流走了。

匿名管道的几个特性

  1. 管道是单双工通信。数据流向只能是从写端流到读端。
  2. 管道提供流式服务,好处就是可以决定读端每次读多少个字节。
  3. 管道的生命周期跟随进程
  4. 匿名管道只支持有亲缘关系的进程进行进程间通信。即先创建管道,再fork子进程。

获取一个文件的权限:

int fcntl(int fd, int cmd, … /* arg */ );
参数解释:

  1. fd:文件描述符
  2. 获取权限:int flag = fcntl(fd,F_GETFL),F_GETEL是宏
  3. 再设置权限:fcntl(fd,F_SETFL,flag | 权限),权限为八进制数字
  4. 当是F_GETFL的时候,返回的是文件描述符的权限信息

管道到底能容纳多大的数据呢?

在这里插入图片描述
输出结果:
在这里插入图片描述
这里涉及到一个点:原子性。

进程在操作匿名管道的时候,如果写入的字节数量小于4K,则保证当前写入操作的原子性。

上述程序会在write程序处阻塞下来,将文件描述符的属性设置为为阻塞态:O_NONBLOCK

在这里插入图片描述
在这块涉及到了两种情况:
1.若是写端文件描述符设置非阻塞状态

读端文件描述符都关闭读端文件文件描述符不关、也不读
现象管道破裂,会导致当前的进程退出写端一直写,直到将管道写满
父进程调用write父进程会退出掉,子进程被1号进程领养再继续写,会返回-1,并报错
子进程调用write子进程会因管道破裂成为僵尸进程和父进程一样

2.若是读端文件描述符设置非阻塞状态

写端文件描述符都关闭写端文件文件描述符不关、也不写
现象读端一直读,直到将管道中的内容读完read 返回-1 ,表示资源不可用
父进程调用read再调用read,会返回0,并报错,没有读到任何内容再继续写,会返回-1,表示资源不可用
子进程调用read和父进程一样和父进程一样

所以在调用read函数的时候,要循环读取,直到有读到内容。

命名管道

命名管道也是在内核中开辟的一段缓冲区,这段缓冲区是有标识符的。则不同的进程,不需要亲缘关系,只需要通过标识符就能找到缓冲区,进行进程间通信。

命名管道的创建

可使用命令行创建:mkfifo filename
可在程序中进行创建:int mkfifo(const char *filename, mode_t mode)
mode:为权限
成功返回0,失败返回-1

命令行创建:
在这里插入图片描述
p:为管道文件。

程序创建:
在这里插入图片描述

在这里插入图片描述

关注一下mkfifo的返回值。

在使用的时候

FIFO为阻塞态FIFO为非阻塞态
读打开FIFO阻塞到有进程为写而打开FIFO立即返回成功
写打开FIFO阻塞到有进程为读而打开FIFO立即返回失败

命名管道的特性

  1. 命名管道的生命周期也是跟随进程的。
  2. 命名管道具有标识符。
  3. 其余特性和匿名管道一样。

数据同样,只读一次,就会被读走。

测试程序:
在这里插入图片描述
在这里插入图片描述
结果为:读取成功。

在这里插入图片描述

在使用命名管道的时候,使用的是一定存在的或已经创建好了的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值