什么是管道?
管道是Unix最古老的进程间通信方式
我们把从一个进程连接到另一个进程的一个数据流称为管道
管道分类
1.匿名管道
#include<unistd.h>
int pipe(int fd[2])
fd:文件描述符数组,其中fd[0]表示读端,fd[1]表示写端
返回值:成功返回0,
代码:
写入管道,再从管道读取
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main()
{
int fds[2];
char buf[100];
int len;
if(pipe(fds)==-1)
perror("make pipe"),exit(1);
while(fgets(buf,100,stdin))
{
len=strlen(buf);
if(write(fds[1],buf,len)!=len)
{
perror("write to pipe");
break;
}
memset(buf,0x00,sizeof(buf));
if((len=read(fds[0],buf,100))==-1)
{
perror("read from pipe");
break;
}
if(write(1,buf,len)!=len)
{
perror("write to stdout");
break;
}
}
return 0;
}
读写特性:
如果管道没有数据,那么read则一直等待,直到有数据
如果管道数据满了,那么write一直等待,直到有数据被读出去
如果所有的写入端关闭 read读完所有数据后返回0;
如果所有的读取端关闭,write出发异常操作会产生信号SIGPIPE,通知我们读取端都关闭了(这个信号会导致我们write端进程推出)
读取的数据量不大于PIPE_BUF,管道可以保证读写的原子性(读写操作不会被打断,造成数据混乱问题)
数据的流式服务,体现的数据的发送和接受的灵活性
数据没有边界,容易粘包(多条数据连接在一起,接收方没办法分辨数据界限)
匿名管道特性:
1.半双工,单向通信。
2.只能用于具有亲缘关系的进程间通信
3.管道的生命周期随进程(打开管道的所有进程推出,管道释放)
4.管道是面向字节流传输数据的
面向字节流:收发数据比较灵活 数据无规则发送,数据无规则边界
5.自带同步互斥
临界资源:大家都能访问的共享资源
临界区: 对临界资源进行操作的代码
同步: 访问的可控时序性(必考)(atm机取钱)
互斥: 对临界资源同一时间的唯一访问性 保护临界资源的安全
2.命名管道
如果我们想在不相关的进程间交换数据,可以使用FIFO文件来完成这项工作,所以它被称为命名管道。
创建管道文件
int mkfifo(const char *name,mode_t mode)
打开管道文件
int fd=open(name,O_RDONLY); 读
int fd=open(name,O_WRONLY); 写
命名管道和匿名管道的区别
1.匿名管道只能适用于语句亲情关系的进程,而命名管道可使用任意进程间
2.匿名管道使用pipe函数创建并打开
3.命名管道使用mkfifo创建,用open打开