Linux-管道

总结这几天学习的知识点,管道


管道的作用就是在具有亲缘关系的进程间传递信息。所谓的亲缘关系,就是他们具有共同的祖先。所以,只要共同的祖先曾今调用调用了fork函数,打开的管道文件就会在fork函数之后。被各个后代进程所共享。

  • 管道是单向通信的,管道的生命周期是随进程的,管道依赖于文件流,管道是面向字节流的。

管道是一种文件,可以调用read,write,close等操作文件的接口来操作管道。另一方面管道不是一种普通的文件,它属于独特的文件系统:pipefs。

管道的本质就是内核维护了的一块缓冲区与管道文件相关联,对管道文件的操作,被内核转换成对这块缓存区 的操作。


然后我们来讲一下管道接口的创建,使用。
管道所用到的所有头文件:

#include<unistd.h>
#include<sys/types.h>
#incldue<errno.h>
#include<stdlib.h>

管道的创建:

int pipe(int pipefg[2])

如果调用成功后会返回0,失败返回-1,并且设置errno。

errno原因
EMFILE该进程的文件描述符多于MAX_OPEN-2
ENFILE系统中同时打开的文件超过了系统的限制
EFAULTpipefd参数不合法

当成功调用后,就会返回俩个文件描述符。一个是管道的读取端的文件描述符pipefd[0],另一个是管道的写入端 的文件描述符pipefd[1]。
管道没有文件名与之关联。所有只能通过文件描述符来访问管道。

然后调用pipe函数后,就可以往管道里写数据:

write(pipefd[1],void *wbuf,size_t count)//这三个参数分别代表:指定输入要源   缓冲区的首地址   缓冲区的大小字节数

一旦对管道里写数据,那就可以在在读取端进行read进行读取数据

read(pipefd[0],void *rbuf,szie_t count)//这三个参数分别代表:指定输入要源   缓冲区的首地址   缓冲区的大小字节数

管道间的通信就是用到了这俩个文件描述符。调用fork函数会在子进程上也复制了父进程的俩个文件描述符。但是管道里是字节流,父子进程都进行读,写。那样就会导致内容混在了一起,所有平常我们就会使父进程放弃读,子进程放弃写,变成父进程写,子进程读,成为了通信的通道。
如何让父进程放弃读,子进程放弃写呢?

close(pipefd[1])//子进程放弃写
close(pipefd[0])//父进程放弃读

我们可以从内核角度看:调用pipe函数后系统会给进程分配俩个文件描述符,然后在调用了fork函数后,子进程也有了对应的文件描述符。和普通文件不同,这俩个文件描述符对应的是一块内存缓存区。
所以,任何俩个有亲缘关系的进程,只要祖先打开了管道,总能通过关闭不相关进程的某些文件描述符,建立起俩者之间单向通信的管道。


管道具有如下三种性质:

  • 只有当写入端的文件描述符都关闭,管道里没有可读的数据,读取端的文件描述符调用read是才会返回0。
  • 如果所有的读取端 的描述符都关闭,在往管道里写数据,写操作会失败,errno会置为EPIPE,同时内核会向写入进程发送一个SIGPIPE的信号。
  • 当所有的读取端,写入端都关闭,管道才能被销毁。

管道对应的内存大小:

管道本质就是一块内存区域,肯定有大小的。管道的默认大小是65536字节,但是可以用fcntl来获取和修改这个值。

pipe_capacity = fcntl(fd,?F_GETPIPE_SZ)//获取管道的大小
ret = fcntl(fd,?F_SETPIPE_SZ,SZ)//设置管道的大小

我们在使用管道 的时候要意识到:管道有大小,写入需谨慎,不能连续的写入大量的内存,一旦管道满了,写入就会阻塞;在读取端,要及时读取,防止管道被写满,造成写入阻塞。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值