• 【Linux】:进程间通信


    一.基本概念

    是什么

    两个或多个进程实现数据层面的交互。

    因为进程独立性的存在,导致进程间的通信成本比较高。

    为什么

    因为我们有多进程协同的需求。

    怎么办

    a.进程间通信的本质:必须让不同的进程看到同一份"资源"。
    b.“资源”?特定形式的内存空间。
    c.这个"资源"谁提供?一般是操作系统。
    d.我们进程访问这个空间,进行通信,本质就是访问操作系统!进程代表的就是用户,“资源”从创建,使用(一般),释放―–需要系统调用接口!一般操作系统会有一个独立的通信模块-隶属于文件系统-IPC通信模块。

    二.简单的通信-管道(匿名管道)

    管道是Unix中最古老的进程间通信的形式。 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。

    在这里插入图片描述

    1.建立通信信道

    管道是一个文件-内存级文件。

    1.管道文件与一般文件不同,一般文件存在于磁盘里,管道文件存在于内存里。也就是说管道文件不需要将修改内容从内存刷新缓冲区到磁盘,这是它的特点。

    2.一般管道文件只能具有血缘关系的进程间通信。因为只有具有血缘关系才能继承同一份files_struct。

    3.一个父进程在创建管道文件时不能只是以读或者写的方式,必须两者都有。操作系统会把这个文件打开两次,分别用来读和写。但操作系统实际上只想让两个进程进行单向通信,因为如果一个进程又在读又在写,很容易会造成数据混淆,为了避免麻烦,规定只能一个进程写,另一个进程读。

    在这里插入图片描述

    这个文件不需要有名字,inode…让操作系统区分。所以这种文件也被称为匿名管道。

    2.通信接口

    在这里插入图片描述

    pipe的作用就是帮助我们以读和写打开文件。它的参数是一个输出型参数,它会把分别以读和写的文件的文件描述符通过参数带出,供用户使用。pipefd[0]一般用于读,pipefd[1]一般用于写。

    模拟

    makefile

    testPipe:TestPipe.cpp
    	g++ -o $@ $^ -std=c++11
    .PHONY:clean
    clean:
    	rm -f testPipe
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    TestPipe.cpp(一个简单的通信,子进程向父进程里写信息)

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    
    using namespace std;
    #define N 2
    #define NUM 1024
    
    //子进程
    void Write(int wfd)
    {
      //任意写几个数据测试
      string s="hello,i am a child";
      pid_t id=getpid();
      int num=0;
    
      char buffer[NUM];
      while(1)
      {
        snprintf(buffer,sizeof(buffer),"%s-%d-%d\n",s.c_str(),id,num++);//将数据都变成字符存在buffer里
        
        //把数据写入管道
        write(wfd,buffer,strlen(buffer));
        sleep(1);
      }
    }
    
    //父进程
    void Read(int rfd)
    {
      char buffer[NUM]={0};
      while(1)
      {
        ssize_t n=read(rfd,buffer,sizeof(buffer));
        if(n>0)
        {
          cout<<buffer<<endl;
        }
        else if(n==0) break;
      }
      
    }
    
    int main()
    {
      int pipefd[N]={0};
      //创建管道
      int n=pipe(pipefd);
      //判断是否创建成功
      if(n<0) return 1;
      
      //创建子进程
      pid_t id=fork();
      if(id<0) return 2;
      if(id==0)
      {
        //子进程
        //关闭读功能
        close(pipefd[0]);
    
        //IPC code
        Write(pipefd[1]);
    
        //退出
        close(pipefd[1]);
        exit(0);
      }
      //父进程
      //关闭写功能
      close(pipefd[1]);
    
      //IPC code
      Read(pipefd[0]);
      //退出
    
      //回收子进程
      pid_t rid=waitpid(id,nullptr,0);
      if(rid<0) return 3;
      close(pipefd[0]);
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

    在这里插入图片描述

    管道的4中情况:
    1.读写端正常,管道如果为空,读端就要阻塞 2读写端正常,管道如果被写满,写端就要阻塞 3.读端正常读,写端关闭,读端就会读到0,表明读到了文件(pipe)结尾,不会被阻塞
    4,写端正常写入,读端被关闭。操作系统就要杀掉正在写入的进程。如何干掉?通过信号杀掉。

    管道的特征:
    1.具有血缘关系的进程进行进程间通信。
    2.管道只能单向通信。
    3.父子进程是会进程协同的,同步与互斥的—保护管道文件的数据安全 4.管道是面向字节流的。
    5.管道是基于文件的,而文件的生命周期是随进程的!

    三.命名管道

    很明显上面的匿名管道只使用于具有血缘关系的通信是远远不够的,为了解决这个问题,又有了命名管道的概念。

    如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
    命名管道是一种特殊类型的文件。

    1.mkfifo

    在这里插入图片描述

    创建一个命名管道命名为myfifo

    在这里插入图片描述

  • 相关阅读:
    fablic 矩形多边形展示删除按钮
    webpack的安全保障是怎么做的?
    回归测试?
    服务注册发现 springcloud netflix eureka
    PyTorch随机生成一个布尔型张量
    车道线算法合集——各个车道线论文代码地址、算法总结、优劣分析
    【C语言 数据结构】顺序表的使用
    VulnHub Alice
    Promise面试实战指北
    SSH本地连接---Hadoop单词统计
  • 原文地址:https://blog.csdn.net/m0_73790767/article/details/134369764