Linux共享内存

共享内存

什么是共享内存?首先我们要了解一个概念,进程间通讯,在程序加载到内存中之后,进程之间都是相互独立的,将两个独立的进程进行通讯,让他们产生关联就是进程之间的通讯,那么如何让两个不相干的进程建立起通讯呢,这个时候就需要用到共享内存了,下面用一张图来认识一下进程通信和共享内存的概念:
Linux共享内存_第1张图片
可以看到,两个不相干的进程通过一个共享内存建立连接,产生通信

下面来用一个小程序来实现一下:
用两个进程,A和B,A向共享内存中写入数据,B从共享内存中读取数据从而达到通信的效果

要想使用共享内存,首先得了解几个接口
1,获取相同的key
ftot(“文件地址”,随机数字);
让两个完全独立的进程共享同一块内存,首先要确保两个进程看见的是同一块内存,因为两个进程的独立,所以首先要让两个进程拥有一个共识性的key,然后用这个key去创建一块共享内存,从而建立连接。

成功生成随机数,返回此随机数
生成失败,返回-1

2,创建共享内存
shmget(key,共享内存大小,创建方式);
要使用共享内存,首先必须要创建共享内存,key是由ftok生成的随机数,来确保进程之间关联的是同一块内存,创建方式有两种:
IPC_CREAT and IPC_EXCL
单独使用IPC_CREAT: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共享内存并返回
IPC_EXCL不能单独使用,一般都要配合IPC_CREAT
IPC_CREAT | IPC_EXCL: 创建一个共享内存,如果共享内存不存在,就创建之, 如果已经存在,则立马出错返回 – 如果创建成功,对应的shm,一定是最新的!

3,关联共享内存
shmat(共享内存id,null,0);
在创建好共享内存之后,要将进程和共享内存关联起来,并不是直接使用,返回值和mallo非常相似,是一个char*类型的指针,可以像malloc的返回值一样,直接用来写数据

4,取消关联共享内存
shmdt(关联共享内存的地址);
在删除共享内存,或者程序结束之前,要取消共享内存的关联,参数是shmat的返回值

5,删除共享内存
shmctl(共享内存id,);

代码实现:

#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;


//获取相同的key来映射同一个共享内存
int GetKey()
{
    int k = ftok(".",0666);
    if(k == -1)
    {
        cerr << errno << strerror(errno) << endl;
        exit(1);
    }

    return k;
}

//创建共享内存
int createshm(int k,int size,int flag)
{
    int shmid = shmget(k,size,flag);
    if(shmid == -1)
    {
        cout << errno <<  strerror(errno) << "共享内存创建失败" << endl;
        exit(2);
    }

    return shmid;
}

//将key转成16进制
string toHex(int x)
{
    char buffer[64];
    snprintf(buffer, sizeof buffer, "0x%x", x);
    return buffer;
}


//创建共享内存,如果共享内存存在返回共享内存的ID
int creatshmid(key_t k, int size)
{
    umask(0);
    return createshm(k,size,IPC_CREAT | IPC_EXCL | 0666);
}

//获取共享内存的id
int getshmid(key_t k, int size)
{
    return createshm(k,size,IPC_CREAT);
}

//删除共享内存
void delshm(int shmid)
{
    int n = shmctl(shmid,IPC_RMID, NULL);
    assert(n != -1);
}

//共享内存关联
char* attshmm(int shmid)
{
    char* start = (char*)shmat(shmid,NULL,0);
    return start;
}

//取消共享内存关联
void datachshm(char* start)
{
    int n = shmdt(start);
    cout << "取消关联" << n << endl;
    assert(n != -1);
}

进程A

#include"comm.h"

//向共享内存写入
int main()
{
    //获取同一个key值
    size_t key = GetKey();
    string strkey = toHex(key);
    cout << "key:" << strkey << endl;
    if(key == -1)
    {
        cout << errno << strerror(errno) << endl;
        exit(1);
    }

    //创建共享内存
    int shmid = creatshmid(key,4096);

    cout << "shmid:" << shmid << endl;

    //共享内存关联
    char* start = attshmm(shmid);
    system("ipcs -m");


    //写入
    char buff[100] = {"i am process A \0"};
    int n = 0;
    while(buff[n] != '\0')
    {
        start[n] = buff[n];
        n++;
    }

    sleep(15);
    //取消共享内存关联
    datachshm(start);

    //删除共享内存
    delshm(shmid);
    cout << "删除成功" << endl;
    system("ipcs -m");

    return 0;

}

进程B

#include"comm.h"

//读取共享内存中的数据
int main()
{
    //获取同一个key值
    size_t key = GetKey();
    string strkey = toHex(key);
    cout << "key:" << strkey << endl;

    if(key == -1)
    {
        cout << errno << strerror(errno) << endl;
        exit(2);
    }

    //找到共享内存
    int shmid = getshmid(key,4096);

    cout << "key:" << key << "  " << "shmid:" << shmid << endl;

     //共享内存关联
    char* start = attshmm(shmid);
    // system("ipcs -m");

    //读取
    cout << start << endl;

    //取消共享内存关联
    datachshm(start);

    // //删除共享内存
    // delshm(shmid);
    return 0;

}

运行效果:
Linux共享内存_第2张图片

你可能感兴趣的:(linux,服务器)