【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
2.void *shmat(int   shmid, const void *shmaddr, int shmflg); 将共享内存映射到进程的地址空间
 
 
 shmaddr:一般给NULL,由系统自动选择映射的虚拟地址空间
 shmflg:不指定时给0
 return 成功返回共享内存的首地址,失败返回NULL
 3.int shmdt(const void    *shmaddr);断开当前进程的shmaddr指向的共享内存映射
 return 成功返回0,失败返回-1

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

a.cpp

#include<iostream>
#include<unistd.h>
#include<cstring>
#include<sys/shm.h>
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);
}

b.cpp

#include<iostream>
#include<unistd.h>
#include<cstring>
#include<sys/shm.h>
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);
}

结果

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

使用信号量进行同步读写

sharedmemory1.cpp

#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#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();
}

sharedmemory2.cpp

#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
#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);



}

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值