• 【Linux进程间通信】共享内存


    原理:多个进程映射到同一块内存

    半双工

    Linux进程通信中最快的

    API

     1.int shmget(key_t key, size_t size, int shmflg);  用于创建或者获取共享内存
       
     - key:不同进程使用相同的key可以获取到同一块内存
     -    size:创建共享内存时,指定要申请的共享内存空间大小,以字节为单位。
     -    shmflg:IPC_CREAT 存在则打开,不存在则创建。
     -    IPC_CREAT与IPC_EXCL一起使用,存在则会报错,不存在则创建
     - return 成功返回共享内存的ID,失败返回-1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    2.void *shmat(int   shmid, const void *shmaddr, int shmflg); 将共享内存映射到进程的地址空间
     
     
     shmaddr:一般给NULL,由系统自动选择映射的虚拟地址空间
     shmflg:不指定时给0
     return 成功返回共享内存的首地址,失败返回NULL
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
     3.int shmdt(const void    *shmaddr);断开当前进程的shmaddr指向的共享内存映射
     return 成功返回0,失败返回-1
    
    • 1
    • 2

    简单案例:一个进程往共享内存中写一次数据然后在另一块共享内存读一次数据,然后另一个进程在一个共享内存读一次数据在另一块共享内存写一次数据(同时验证了它是半双工的)

    a.cpp

    #include
    #include
    #include
    #include
    int main()
    {
     int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
        if(-1 == shmid)
        {
            std::cout<<"shmget erro"<<std::endl;
            exit(-1);
        }
        char * s = (char *)shmat(shmid,nullptr,0);
        if(s == (char *)-1)
        {
            std::cout<<"shmat erro"<<std::endl;
        }
        int shmid2 = shmget((key_t)123457,128,IPC_CREAT|0600);
        if(-1 == shmid2)
        {
            std::cout<<"shmget erro"<<std::endl;
            exit(-1);
        }
        char * s2 = (char *)shmat(shmid2,nullptr,0);
        if(s2 == (char *)-1)
        {
            std::cout<<"shmat erro"<<std::endl;
        }
        strcpy(s,"hello1");
        sleep(1);
        std::cout<<s2;
        shmdt(s);
        shmdt(s2);
        exit(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

    b.cpp

    #include
    #include
    #include
    #include
    int main()
    {
        int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
        if(-1 == shmid)
        {
            std::cout<<"shmget erro"<<std::endl;
            exit(-1);
        }
        char * s = (char *)shmat(shmid,nullptr,0);
        if(s == (char *)-1)
        {
            std::cout<<"shmat erro"<<std::endl;
        }
        int shmid2 = shmget((key_t)123457,128,IPC_CREAT|0600);
        if(-1 == shmid2)
        {
            std::cout<<"shmget erro"<<std::endl;
            exit(-1);
        }
        char * s2 = (char *)shmat(shmid2,nullptr,0);
        if(s2 == (char *)-1)
        {
            std::cout<<"shmat erro"<<std::endl;
        }
        std::cout<<s;
        strcpy(s2,"hello2");
        shmdt(s);
        shmdt(s2);
        exit(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

    结果

    在这里插入图片描述
    在这里插入图片描述

    使用信号量进行同步读写

    sharedmemory1.cpp

    #include
    #include
    #include
    #include
    #include"sem.h"
    int main()
    {
     int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
     if(shmid == -1)
     {
    
       std::cout<<"shmget erro"<<std::endl;
         exit(1);
     }
     char * s=(char *)shmat(shmid,NULL,0);
     if(s== (char *)-1)
     {
      std::cout<<"shmat erro"<<std::endl;
      exit(1);
     
     }
     sem_init();
      while(1)
      {
         sem_p(SEC);
         if(strncmp(s,"end",3) !=0)
         {
            std::cout<<s<<std::endl;
         }else
         {
            break;
         }
        
        sem_v(FIR);
    
     }
      
       shmdt(s);
       sem_destory();
    }
    
    • 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

    sharedmemory2.cpp

    #include
    #include
    #include
    #include
    #include
    #include"sem.h"
    int main()
    {
     int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
     if(shmid == -1)
     {
    
         std::cout<<"shmget erro\n"<<std::endl;
         exit(1);
     }
     char * s=(char *)shmat(shmid,NULL,0);
     if(s== (char *)-1)
     {
      std::cout<<"shmat erro"<<std::endl;
      exit(1);
     
     }
     sem_init();
     while(1)
    {
      char buff[128]={0};
      std::cout<<"input "<<std::endl;
      fgets(buff,127,stdin);
        sem_p(FIR);
        strcpy(s,buff);
        sem_v(SEC);
      if(strncmp(buff,"end",3) ==0)
      {
        break;
      }
    }
    
     shmdt(s);
    
    
    
    }
    
    • 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

    结果
    在这里插入图片描述
    在这里插入图片描述

    ipcs -m:输出所有共享内存(share memory)信息
    在这里插入图片描述
    key:表示共享内存的key
    shmid:表示共享内存编号
    owner:表示创建共享内存的用户
    perms:表示共享内存的的使用权限
    bytes:表示共享内存的大小
    nattch:表示连接到共享内存的的进程数
    status:表示共享的状态(不显示则为正常使用,显示“dest”表示已被标记,但并未真正删除,当这块内存的引用计数为0后则会被删除)

    ipcs -lm:输出共享内存(share memory)控制信息
    在这里插入图片描述

  • 相关阅读:
    一款.NET Core开源的基于Vue+ElementUI开发的博客系统 - StarBlog
    入行数字IC验证的一些建议
    设计模式之模板方法模式
    Linux常用命令——consoletype命令
    《中国棍网球》:体育项目·棍网球
    PyTorch分布式backends
    LM2904DT运算放大器中文资料规格书PDF数据手册引脚图参数图片功能概述
    Linux性能优化--使用性能工具发现问题
    软件工程概论
    【Linux】基础IO —— 上
  • 原文地址:https://blog.csdn.net/aoeaoao/article/details/127940097