管道:有名管道、无名管道
1 .有名管道(FIFO文件/命名管道)
通常应用于任意两个进程间的通讯,它是一种特殊的文件,在磁盘上有一个文件标识,创建管道文件,但是,交互的数据并不会存储到磁盘中,管道文件不会占据磁盘空间。
注:A、B两个进程通过管道文件(文件系统)访问内存上的同一块空间。
//创建管道文件:
命令: mkfifo filename
#include<sys/types.h>
#include<sys/stat.h>
函数: int mkfifo(char *filename,int mode)
有名管道的例子
先创建一个管道文件——“fifo”,两个.c 文件(write.c 和 read.c)分别对这个管道文件读和写。
可以看到运行时,首先两边都得到了自己的文件描述符,
两个程序都不再运行!
原因是阻塞住了,写段没有开始输入,读端自然等待写段写入
依次输入,读端也都打印了出来
总结:
-
管道有读端和写段之分
open函数会阻塞运行,保证至少有一个读进程,一个写进程
当写端关闭之后,读端read会返回0,随后关闭 -
当读端没有数据可读,read调用就会阻塞,即它将暂停读端进程等待有数据到达为止。这种阻塞没有多大用处,所以在read会返回0,在写端中的if(n<=0)就是去应对这种阻塞。
2.无名管道
顾名思义,无名管道就是没有名字的管道,它不是以文件的形式存储到文件系统中,只能借助于父子进程共享文件描述符,不会创建管道文件,只能应用于父子进程之间的通讯。
//创建并打开无名管道
#include<unistd.h>
int pipe(int fds[2]);//fds[0]读文件描述符 fds[1]写文件描述符
规定:父子进程执行之前,必须分别关闭一对读写!
3.管道的原理
内部实现方式:队列(环形队列)。
管道中有头指针:负责写。
管道中有尾指针:负责读。
刚开始头尾指针都指向头。
写数据是头指针不断向后移动,管道写满后又回头部循环写入,遇到尾指针(管道满,写阻塞)则无法写入
当尾指针读时遇到头指针(管道空,读阻塞)则读取结束
缓冲区大小:默认4k,内核会适当的调整,但有一定范围,不会无限放大
4、管道的局限性
基于队列的数据结构,数据只能读取一次,不能重复读取。
半双工——>可以定义双向,但不能同时工作