- 什么是管道
- 管道是Unix中最古老的进程间通信的形式;
- 管道是半双工的,数据只能向一个方向流动;
- 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)进行通信;????
- 本质上是文件io操作;
- 最大的数据量为65556(64kb);
- 在shell中使用管道
- 命令格式如:cmd1 | cmd2;这种信息过滤也是通过管道实现
- 优缺点
- 能进行块数据的传输;
- 内容有上限;
- 要双端同时打开才能使用;
匿名管道pipe
关键函数
//准备文件描述符:fd[0]读、fd[1]写
int fdarr[2] = { 0 };
//创建管道:利用文件描述符数组,第一个读、第二个写
pipe(fdarr) != 0 //打开一个管道
//管道只能是单向的,读端关闭fd[1]、写端关闭fd[0]
close(fdarr[0])
// 读写操作
//写端
write(fdarr[1], buf, sizeof(buf));
//读端
read(fdarr[0], buf, sizeof(buf));
用pipe无名管道实现父子进程间通信
#include<iostream>
#include <unistd.h>
using namespace std;
#include<string.h>
//匿名管道的训练
int main()
{
int fdarr[2] = { 0 };//负责父-》子 fd[0]读、fd[1]写
int fdarr2[2] = { 0 };//负责子-》父
char buf[50] = { 0 };
char resbuf[50] = { 0 };
pid_t pid = 0;
if (pipe(fdarr) != 0 || pipe(fdarr2) != 0)
{
perror("pipe error");
}
else {
pid = fork();
if (pid > 0)
{//父亲
//管道的读端关闭,执行写
close(fdarr[0]);
close(fdarr2[1]);
while (1)
{
cout << "父进程发送:" << endl;
fgets(buf, sizeof(buf),stdin);
int wres = write(fdarr[1], buf, sizeof(buf));
cout << "pid = " << getpid() << " 发送:" << buf << " res = " <<wres <<endl;
bzero(buf, sizeof(buf));
int res = read(fdarr2[0], buf, sizeof(buf));
cout << "pid = " << getpid() << " 接收:" << buf<< " res = " << res <<endl;
bzero(buf, sizeof(buf));
}
}
else if (pid == 0)
{
close(fdarr[1]);
close(fdarr2[0]);
while (1)
{
int res = read(fdarr[0], resbuf, sizeof(resbuf));
cout << "pid = " << getpid() << " 接收:" << buf << " res = " << res << endl;
bzero(resbuf, sizeof(resbuf));
cout << "子进程发送:" << endl;
fgets(buf, sizeof(buf), stdin);
int wres = write(fdarr2[1], buf, sizeof(buf));
cout << "pid = " << getpid() << " 发送:" << buf << " res = " << wres << endl;
bzero(buf, sizeof(buf));
}
}
}
}
- Fork前创建管道,获得读端和写端的文件描述符、fork后关闭不需要的管道;
- 匿名管道不能修改通信方向(close(fdarr[0]));
命名管道fifo
//检测是否存在
access(pipepath.c_str(), F_OK)
//创建管道
mkfifo(pipepath.c_str(), 0007)
//写端
open(pipepath.c_str(), O_WRONLY)
write(Writefd, wbuf, sizeof(wbuf))
//读端
open(pipepath.c_str(), O_RDONLY)
read(Readfd, rbuf, sizeof(rbuf))
命名管道-伪聊天
#include<iostream>
using namespace std;
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <strings.h>
int main()
{
string pipepath = "/home/wangcf/data/A2B.pipe";
int wfd = 0;
int Writefd = 0;
char wbuf[50] = { 0 };
string pipepath2 = "/home/wangcf/data/B2A.pipe";
int rfd = 0;
int Readfd = 0;
char rbuf[50] = { 0 };
umask(0);
if (access(pipepath.c_str(), F_OK) == 0)
{
cout << "pipe existence存在" << endl;
}
else {
if(mkfifo(pipepath.c_str(), 0007) == -1)
{
perror("mkfifo error");
}
}
if (access(pipepath2.c_str(), F_OK) == 0)
{
cout << "pipe2 existence存在" << endl;
}
else {
if (mkfifo(pipepath2.c_str(), 0007) == -1)
{
perror("mkfifo error");
}
}
Writefd = open(pipepath.c_str(), O_WRONLY);
if (Writefd == -1)
{
perror("open error");
}
else {
cout<< "Writefd = " <<Writefd << endl;
}
Readfd = open(pipepath2.c_str(), O_RDONLY);
if (Readfd == -1)
{
perror("open error");
}
else {
cout << "Readfd = " << Writefd << endl;
}
wfd = fork();
if (wfd == 0)
{
//写端
while (1)
{
cin >> wbuf;
int wres = write(Writefd, wbuf, sizeof(wbuf));
cout << "A :" << wbuf << endl;
bzero(wbuf, sizeof(wbuf));
}
}
else if (wfd > 0)
{
while (1) {
int rres = read(Readfd, rbuf, sizeof(rbuf));
cout << "B :" << rbuf << endl;
bzero(rbuf, sizeof(rbuf));
}
}
return 0;
}
- Open函数
- 是阻塞式函数,一定要两段同时开启;
- 程序不能以O_RDWR模式打开FIFO文件进行读写;
- Read()为阻塞函数;
- 命名管道可以修改通信方向:
- (先关闭再重新打开FIFO的办法明确地改变数据流的方向);
- Fifo文件
- 不会保留数据,永远大小为0;
- 把管道删掉还能用,但是不合规。
用管道实现伪聊天!!!!!
未实现