c++ 匿名函数_Linux亲缘进程间通信:匿名管道

6f4de209d2353b8044f7c23aa8202dce.png

图控大叔

构图传递思想

阅读从未如此简单!!!

01

前言

       今天来说说Linux进程间通信:匿名管道。Linux环境下,进程间的通信方式有很多,有管道,IPC机制下的消息队列、共享内存和信号量,Posix机制下的有名信号量和无名信号量。今天要分享的内容是亲缘进程间的通信方式:匿名管道。待分享的内容还很多,慢慢来!

02

细述

ada82a7f274a91608188035a57b0d6e1.gif匿名管道的特点
匿名管道,又称无名管道
特点:

  1,它只能作用于亲缘进程
    1.1、匿名管道的创建使用pipe创建,诞生出两个操作管道读写端的文件描述符
    1.2、只有创建子进程的时候才会被继承过去,无法通过别的方式打开同一个管道
    
  2,半双工通信(在读的时候不能写入,在写入的时候不能读取)
  
  3,操作无原子性
  
  4,无法用lseek定位操作位置
  
  5,匿名管道比命名管道需要更少的开销,但是提供有限的服务。
  
管道的特点在于他本身拥有读写阻塞特性,
  你可以利用这一个特性制造出属于自己的特殊的缓冲区(数据的同步互斥特性)
ada82a7f274a91608188035a57b0d6e1.gif相关API
匿名管道需包含头文件
#include 

匿名管道相关API
1、创建匿名管道
  int pipe(int pipefd[2]);
  
2、读操作
  read(pipefd[0], file, sizeof(file)));
  
3、写操作
  write(pipefd[1], file, sizeof(file)));
  
4、关闭:关闭文件描述符
  close(pipefd[0]);
  close(pipefd[1]);
ada82a7f274a91608188035a57b0d6e1.gif部分函数说明
匿名管道创建函数
int pipe(int pipefd[2]);

函数功能:
  随机创建一个匿名管道,并且返回管道的两个通信文件描述符给传入的数组
  pipefd:这是一个(两个int型元素的数组),
    管道创建成功后会将读端文件描述符放到第0个元素中,
      读端:pipefd[0]
    将写端文件描述符放到第1个元素中
      写端:pipefd[1]
  返回值:
    成功返回0,失败返回-1
ada82a7f274a91608188035a57b0d6e1.gif其他说明
其他说明
  1、匿名管道的使用只能在亲缘进程间
  
  2、匿名管道在父、子进程继承的时候,管道依旧是一个管道,
    但是每个进程都拥有自己的文件描述符,
    即读端:pipefd[0]
      写端:pipefd[1]
     因此,父进程的读端关闭,仅影响父进程的读端操作,
     不影响子进程的读端操作。反之亦然
ada82a7f274a91608188035a57b0d6e1.gif参考代码
#include 
#include 
#include 
#include 

int main(void){
  int pipe_fd[2];
  int retval;
  pid_t cpid;
  char buffer[1024];

  retval = pipe(pipe_fd);
  if(retval == -1)
  {
    perror("create pipe error");
    return -1;
  }
  cpid = fork();
  if(cpid == 0)
  {
    ssize_t rd_ret;
    int C_write_num = 0;
    int C_read_num = 0;
    while(1)
    {
      bzero(buffer, sizeof(buffer));
      rd_ret = write(pipe_fd[1], "子进程写进去的", strlen("子进程写进去的"));
      
      if(rd_ret == -1)
      {
        perror("子进程写失败\n\n");
        //exit(EXIT_FAILURE);为了观察实验现象而注释
      }
      
      if(C_write_num == 6)
      {
        close(pipe_fd[1]);
        printf("子进程 写端关闭\n\n");
        
        rd_ret = read(pipe_fd[0], buffer, sizeof(buffer));
        if(rd_ret == -1)
        {
          perror("子进程 读端失败\n");
          exit(EXIT_FAILURE);
        }
        C_read_num++;
        printf("子进程 第 %d 读结束 %s\n\n", C_read_num,buffer);
        sleep(1);
      }
      else
      {
        C_write_num++;
        printf("子进程 第 %d 写结束 \n\n", C_write_num);
        sleep(1);
      }
    }
    exit(EXIT_SUCCESS);
  }
    ssize_t rd_ret_2;
    int F_write_num = 0;
    int F_read_num = 0;
  while(1)
  {
      bzero(buffer, sizeof(buffer));
      rd_ret_2 = read(pipe_fd[0], buffer, sizeof(buffer));
      
      if(rd_ret_2 == -1)
      {
        perror("父进程读失败\n\n");
        //exit(EXIT_FAILURE);为了观察实验现象而注释
      }
      
      if(F_read_num == 6)
      {
        F_write_num++;
        close(pipe_fd[0]);
        rd_ret_2 = write(pipe_fd[1], "父进程写入的", strlen("父进程写入的"));
        if(rd_ret_2 == -1)
        {
          perror("父进程写失败\n");
          exit(EXIT_FAILURE);
        }
        printf("父进程开始第 %d 次写入的\n\n",F_write_num);
        sleep(1);
      }
      else
      {
        F_read_num++;
        printf("父进程是第 %d 次读取的是 %s\n\n", F_read_num,buffer);
        sleep(1);
      }
  }
  close(pipe_fd[0]);
  close(pipe_fd[1]);

  return 0;
}
ada82a7f274a91608188035a57b0d6e1.gif参考代码说明
首先
   并且往pipe_fd数组当中的0元素填充管道的读端文件描述符,
   往1元素填充管道写端文件描述符
  
其次
   通过fork函数创建子进程
  
再者
   通过在子进程及父进程中设置读、写6次后,
   进行相应的读、写端文件描述符关闭,并且进行打印测试

最后
    观察实验现象

说明,在此处有注释的情况,是为了更好的观察现象,如
    //exit(EXIT_FAILURE);
    而在正常情况下不能关闭

03

结尾

       今天的分享就到这里,系统编程系列的内容还有很多内容需要分享,再接再厉!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值