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