管道是进程通信的一种方式。(进程通信需要让不同进程看到同一份资源)
管道分为匿名管道和命名管道两种。
管道只允许单向通信。
一.匿名管道
#include<iostream>
#include <unistd.h>
#include<cassert>
#include<cstring>
#include<errno.h>
#include<string>
#include <sys/types.h>
#include <sys/wait.h>
//父写子读
int main()
{
//父进程创建管道
int pipefd[2] = {0};
int n = pipe(pipefd);
assert(n == 0);
(void*)n;
std::cout << "pipefd[0]" << pipefd[0] << "pipefd[1]" << pipefd[1] << std::endl;
//创建子进程
pid_t id = fork();
if(id < 0)
{
perror("fork false\n");
return 1;
}
if(id == 0) //子进程读
{
close(pipefd[1]); //关闭写
//to do
while(true)
{
char ret[100];
ssize_t n = read(pipefd[0], ret, sizeof(ret) - 1);
if(n > 0)
{
ret[n] = '\0';
std::cout << "child read:" << ret << std::endl;
}
else if(n == 0)//代表read读不到内容时返回0
{
break;
}
}
//关闭所有fd
close(pipefd[0]);
exit(0);
}
//父进程
close(pipefd[0]); //关闭读
//to do
std::string s = "i am father";
write(pipefd[1], s.c_str(), strlen(s.c_str()));
sleep(5);
//关闭所有fd
close(pipefd[1]);
//回收子进程
pid_t rid = waitpid(id, nullptr, 0);
if(rid == id)
{
std::cout << "wait success" << std::endl;
}
return 0;
}
二.命名管道
1.命令行创建命名管道
【】$ mkfifo filename
2.代码创建
![](https://i-blog.csdnimg.cn/blog_migrate/13ce184240d574ba137ec9016e44f56a.png)
A写B读
#include<iostream>
#include<cassert>
#include<cstring>
#include<errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//A写 B读
int main()
{
//创建命名管道
int n = mkfifo("fifo", 0666);
if(n < 0)
{
perror("mkfifo false\n");
return 1;
}
int fd = open("fifo", O_WRONLY);
if(fd < 0)
{
perror("open fail\n");
return 1;
}
//写入内容
std::string ms = "i am process A";
write(fd, ms.c_str(), ms.size());
close(fd);
return 0;
}
#include<iostream>
#include<cassert>
#include<cstring>
#include<errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("fifo", O_RDONLY);
if(fd < 0)
{
perror("open fail\n");
return 1;
}
//读取内容
char ret[1024];
while(true)
{
ssize_t n = read(fd, ret, sizeof(ret) - 1);
if(n > 0)
{
ret[n] = '\0';
std::cout << "B read :" << ret << std::endl;
}
else if(n == 0)
{
break;
}
}
close(fd);
return 0;
}
三.管道4种情况,5种特性
a.5种特性:
1.匿名管道,只允许具有血缘关系的进程之间进行通信,常用于父子;
命名管道,任意进程。
2.管道默认给读写端提供同步机制
3.面向字节流的
4.管道的生命周期是随进程的
5.管道是单向通信的(一个进程读,另一进程写)
b.4种情况
1.如果管道没有数据了,读端必须等待,直到有数据为止(写端写数据)。
2.如果管道被写满了,写端必须等待,直到有空间为止(读端读走数据)
3.写端关闭,读端一直读取,读端会读到read返回值为0,表示文件结尾
4.读端关闭,写端一直写,os会直接杀掉写端进程,通过向目标进程发送SIGPIPE(13)信号,终止目标进程。