Linux:匿名管道的阻塞属性

管道阻塞特性(10个):

1.管道是半双工通信,数据流只能从写端流向读端

ps aux | grep mypipe
ps aux命令通过写端往管道中写,grep通过读端进行读,数据流向是从写端到读端

从PCB角度去理解管道:

  • 当前进程调用pipe函数,进程里有一个task_struct结构体;
  • task_struct结构体中有一个struct files_struct* files的指针;
  • 该指针指向对应的结构体struct files_struct;
  • 在这个结构体中有一个fd_array的数组;
  • 数组的每一个元素是struct_file*的结构指针 ;
  • 数组的下标为文件描述符,012分别对应标准输入、输出、错误;
    在刚写的代码里3和4是fd[0]和fd[1],如果在创建代码前打开其它文件,那么3和4对应的就不是管道;

fd[0]和[1]对应的是内核中的一块缓冲区,f[0]相当于在缓冲区读,fd[1]相当于往缓冲区里写,该缓冲区就有读写两端

2.匿名管道在内核中创建的缓冲区是没有标识符(没有名字)
  • 导致其它进程无法直接找到这个缓冲区;
  • 但是创建的进程可以通过两个读写端的文件描述符访问
  • 假设a进程创建管道,但其它进程不能使用该管道,但是管道是用来进程间通信,所以这就引出第三个特性
3.匿名管道只支持具有亲缘性关系的进程进行进程间的通信

原理:

  • 用父子进程,子进程会拷贝父进程的PCB中的3,4文件描述符,
  • 父子进程的fd[0]同时指向管道读端,fd[1]同时指向管道写端;
  • 此时父子进程可以通信

在进行父子进程间通信时,一定要父进程先创建管道,再创建子进程,此时子进程的文件描述符表当中才会有匿名管道的读写两端的文件描述符
代码:
在这里插入图片描述
运行结果:
在这里插入图片描述

现让父进程进行写子进程进行读,操作该缓冲区;
代码:
在这里插入图片描述

4.当文件描述符保持基础属性(阻塞属性),调用read函数读空管道时,read函数就会阻塞
  • 文件描述符的基础属性是阻塞属性
  • 父子进程是抢占式运行的,为防止进程读到空管道;
  • 并且文件描述符保持基础属性(阻塞属性),调用read函数读空管道时,read函数就会阻塞;
  • 等待父进程写了之后再读取返回(阻塞属性不止应用于管道);
5.管道的默认大小为 65536字节 → 2^16 → 64k

如何测试一个管道的大小:代码如下
最后count有多少个就有多少个字节
在这里插入图片描述

所以管道的默认大小是64k

6.当文件描述符保持基础属性(阻塞属性),一直调用write函数将管道写满时,write函数会阻塞

上述程序并没有停止,用命令查看程序正在写阻塞
在这里插入图片描述

7.管道的生命周期跟随进程

创建管道的进程结束,管道也就不存在了

8.管道提供字节流服务

字节流:描述的是前后两个数据间是没有明显边界的

字节流缺点:

  • 用户用write函数两次写入字符串,对于管道来说两次输入的数据没有明显边界对用户来说是两次输入,有明显界限
  • read可以读任意字节大小,在读取时无法区分两次输入,前后两次输入粘连在一起,read的返回值是读取到数据的字节数

字节流优点:

  • 可以接收任意字节大小,由用户指定
9.从管道中读取的方式:读取数据是直接将数据拿走,并不是拷贝

验证:再次用read函数读取,管道为空,函数会阻塞不会执行后面语句

10.对管道进行读写的时,读写的字节大小未超过pipe_size,则管道保证读写的原子性原子性

原子性:要么已操作完成,要么未开始,不存在中间状态

pipe size的大小是(512字节*8)=4096字节在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值