管道是进程通信的一种方式。(进程通信需要让不同进程看到同一份资源)
管道分为匿名管道和命名管道两种。
管道只允许单向通信。
一.匿名管道
#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 dowhile(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;}}//关闭所有fdclose(pipefd[0]);exit(0);}//父进程close(pipefd[0]); //关闭读//to dostd::string s = "i am father";write(pipefd[1], s.c_str(), strlen(s.c_str()));sleep(5);//关闭所有fdclose(pipefd[1]);//回收子进程pid_t rid = waitpid(id, nullptr, 0);if(rid == id){std::cout << "wait success" << std::endl;}return 0;
}
二.命名管道
1.命令行创建命名管道
【】$ mkfifo filename
2.代码创建
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)信号,终止目标进程。