管道:ipc
特性:半双工通信----可以选择方向的单向通信
本质:系统内核中的一块缓存区(内核空间中开辟的一块内存)
通信原理:多个进程只要能够访问同一块内核中的缓冲区(管道)就能实现通信。
分类:匿名管道,命名管道
匿名管道:只能用于具有亲缘关系的进程间通信
命名管道:可以用于同一主机上任意进程间通信
匿名管道:
管道缓冲区没有标识符,无法被其他进程找到,因此只能通过子进程复制父进程的方式获取到管道的操作句柄,进行通信
代码操作:
int pipe(int pipefd[2]);
pipefd[0]:用于从管道读数据
pipefd[1]:用于从管道写数据
返回值:成功返回0;失败返回-1;
通过IO操作完成对管道的操作
读写特性:
1.若管道中没有数据,则read会阻塞(暂停3s后执行)
#include<stdio.h> //printf
#include<string.h> //
#include<unistd.h> //fork
#include<stdlib.h> //exit
int main(int argc,char* argv[]) //运行参数个数 运行参数字符串首地址
{
//1.创建管道
//2.创建父子进程
//2.1子进程读数据
//2.2父进程写数据
//1.创建匿名管道
int pipefd[2]; //创建读写入口
int ret=pipe(pipefd); //创建管道
if(ret<0){
perror("pipe error\n");
return -1;
}
//2.创建父子进程
pid_t pid=fork(); //创建进程
if(pid<0){
perror("fork error");
exit(-1); //退出进程
}else if(pid==0){
//child
char buf[1024]={0};
int ret=read(pipefd[0],buf,1023); //读数据
if(ret<0){
perror("read error\n");
}
printf("buf:%s\n",buf);
}else{
//父进程
sleep(3);
char *ptr="今天开心吗?\n";
int ret=write(pipefd[1],ptr,strlen(ptr)); //写入数据
if(ret<0){
perror("write error\n");
return -1;
}
printf("写入成功\n");
}
return 0;
}
2.若管道中数据满了,则write会阻塞(写入10s后运行读端)
效果:写满了就无法写入
//2.创建父子进程
pid_t pid=fork(); //创建进程
if(pid<0){
perror("fork error");
exit(-1); //退出进程
}else if(pid==0){
//child
sleep(10);
char buf[1024]={0};
int ret=read(pipefd[0],buf,1023); //读数据
if(ret<0){
perror("read error\n");
}
printf("buf:%s\n",buf);
}else{
//父进程
sleep(0.5);
int total=0;
char *ptr="今天开心吗?\n";
while(1){
int ret=write(pipefd[1],ptr,strlen(ptr)); //写入数据
if(ret<0){
perror("write error\n");
return -1;
}
total+=ret;
printf("写入成功:%d\n",total);
}
}
3.若管道的所有读端被关闭,则继续write就会触发异常-导致进程退出
//2.创建父子进程
pid_t pid=fork(); //创建进程
if(pid<0){
perror("fork error");
exit(-1); //退出进程
}else if(pid==0){
//child
close(pipefd[0]); //关闭读端
sleep(100);
char buf[1024]={0};
int ret=read(pipefd[0],buf,1023); //读数据
if(ret<0){
perror("read error\n");
}else if(ret==0){
printf("all write closed\n");
}
printf("buf:%s\n",buf);
}else{
//父进程
close(pipefd[0]);//关闭读端
sleep(1);
int total=0;
char *ptr="今天开心吗?\n";
while(1){
int ret=write(pipefd[1],ptr,strlen(ptr)); //写入数据
if(ret<0){
perror("write error\n");
return -1;
}
total+=ret;
printf("写入成功:%d\n",total);
}
}
4.若管道的所有写端被关闭,read读完所有数据后,则不再阻塞,返回0
//2.创建父子进程
pid_t pid=fork(); //创建进程
if(pid<0){
perror("fork error");
exit(-1); //退出进程
}else if(pid==0){
//child
close(pipefd[1]); //关闭写端
sleep(1);
char buf[1024]={0};
int ret=read(pipefd[0],buf,1023); //读数据
if(ret<0){
perror("read error\n");
}else if(ret==0){
printf("all write closed\n");
}
printf("buf:%s\n",buf);
}else{
//父进程
close(pipefd[1]);//关闭写端
sleep(100);
int total=0;
char *ptr="今天开心吗?\n";
while(1){
int ret=write(pipefd[1],ptr,strlen(ptr)); //写入数据
if(ret<0){
perror("write error\n");
return -1;
}
total+=ret;
printf("写入成功:%d\n",total);
}
}