进程间通信--匿名管道

管道: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);
    }
   }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值