目录
一、匿名管道
1.什么是管道?什么是匿名管道?
2.怎么创建匿名管道(函数)
3.匿名管道的4种情况
4.匿名管道有5种特性
5.怎么使用匿名管道?匿名管道有什么用?(例子)
二、命名管道
1.什么是命名管道?
2.怎么创建命名管道(函数)?
3.命名管道的打开规则
4.怎么使用命名管道?命名管道有什么用?(例子)
三、匿名管道和命名管道的区别
一、匿名管道
1.什么是管道?什么是匿名管道?
我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。而匿名管道顾名思义,就是一种没有名字的“管道”。
2.怎么创建匿名管道(函数)
#include <unistd.h>
功能:创建一无名管道
原型
int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端记忆方法:0像一张嘴,所以是读端,1像一支笔,所以是写端
返回值:成功返回0,失败返回错误代码
3.匿名管道的4种情况
1.正常情况,如果管道没有数据了,读端必须等待,直到有数据为止(写端写入数据了)
2.正常情况,如果管道被写满了,写端必须等待,直到有空间为正(读端读走数据)
3.写端关闭,读端一直读取,读端会读到read返回值为0,表示读到文件结尾
4.读端关闭,写端一直写入,OS会直接杀掉写端进程,通过向目标进程发送SIGPIPE(13)信号,终止目标进程
b.管道的5种特性
1.匿名管道,可以允许具有血缘关系的进程之间进行进程间通信,常用与父子,仅限于此
2.匿名管道,默认给读写端要提供同步机制 ---了解现象就行
3. 面向字节流的---了解现象就行
4.管道的生命周期是随进程的
5.管道是单向通信的,半双工通信的一种特殊情况
4.匿名管道有5种特性
1.匿名管道,可以允许具有血缘关系的进程之间进行进程间通信,常用与父子,仅限于此
2.匿名管道,默认给读写端要提供同步机制
3. 面向字节流的
4.管道的生命周期是随进程的
5.管道是单向通信的,半双工通信的一种特殊情况
5.怎么使用匿名管道?匿名管道有什么用?(例子)
例子:
先创建管道, 进而创建子进程, 父子进程使用管道进行通信
父进程向管道当中写“i am father”,
子进程从管道当中读出内容, 并且打印到标准输出(屏幕)
#include <unistd.h>
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int fd[2];
//打开匿名管道
if(pipe(fd) == -1)
{
cout << "open pipe fail" << endl;
exit(1);
}
pid_t id = fork();
if(id == 0)//child
{
char message[30];
read(fd[0], message, sizeof(message));
cout << message << endl;
}
//father
char s[] = "i am father";
write(fd[1], s, sizeof(s));
return 0;
}
运行后:
二、命名管道
1.什么是命名管道?
匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文件。
2.怎么创建命名管道(函数)?
命名管道可以从命令行上创建,命令行方法是使用下面这个命令
mkfifo filename
命名管道也可以从程序里创建,相关函数有
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename,mode_t mode);
filename:命名管道的名字
mode:权限值
返回值:成功返回0,失败返回-1
3.命名管道的打开规则
如果当前打开操作是为读而打开FIFO时
- O_NONBLOCK (disable):阻塞直到有相应进程为写而打开该FIFO
- O_NONBLOCK (enable):立刻返回成功
如果当前打开操作是为写而打开FIFO时
- O_NONBLOCK (disable):阻塞直到有相应进程为读而打开该FIFO
- O_NONBLOCK (enable):立刻返回失败,错误码为ENXIO
4.怎么使用命名管道?命名管道有什么用?(例子)
创建出来的命名管道可以供两个进程通信
进程A 向管道当中写 “i am process A”
进程B 从管道当中读 并且打印到标准输出
processA.cc
#include "fifo.h"
using namespace std;
bool MakeFifo()
{
int n = mkfifo(FIFONAME, 0644);
if(n < 0)
{
cout << "mkfifo fail" << endl;
return false;
}
return true;
}
int main()
{
//创建命名管道
if(!MakeFifo())
{
cerr << "mkfifo fail" << endl;
return 1;
}
//打开fifo文件写
int wfd = open(FIFONAME, O_WRONLY);
if(wfd < 0)
{
cerr << "open fifo fail" << endl;
return 2;
}
cout << "Process A is sending a message to process B" << endl;
char message[] = "i am process A";
write(wfd, message, sizeof(message));
return 0;
}
processB.cc
#include "fifo.h"
using namespace std;
int main()
{
//打开fifo文件写
int rfd = open(FIFONAME, O_RDONLY);
if(rfd < 0)
{
cerr << "open fifo fail" << endl;
return 2;
}
cout << "receives messages from process A: ";
char message[30];
read(rfd, message, sizeof(message));
cout << message << endl;
return 0;
}
fifo.h
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include <cassert>
#include <fcntl.h>
#include <unistd.h>
#define FIFONAME "fifo"
现象:
1.
2.
3.
三、匿名管道和命名管道的区别
- 匿名管道由pipe函数创建并打开。
- 命名管道由mkfifo函数创建,打开用open
- FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义