共享内存概念
共享内存允许两个不相关的进程去访问同一部分逻辑内存 如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案
共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址空间中。 其他进程可以把同一段共享内存段“连接到”它们自己的地址空间里去。 所有进程都可以访问共享内存地址,就好像它们是有malloc分配的一样 如果一个进程向这段共享内存写了数据,所做的改动会立刻被有权访问同一段共享内存的其他进程看到
关于共享内存的操作
以下代码创建一块共享内存
#include<stdio.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<string.h>
int main()
{
int shmid = shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);
printf("shmid = %d\n",shmid);
return 0;
}
但实际我们要这样创建,先删除之前可能存在的内存,在创建一块自己的内存
#include<stdio.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<string.h>
int main()
{
int shmid = shmget((key_t)1234,0,0);
if(shmid > 0)
{
shmctl(shmid,IPC_RMID,0);
shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);
printf("shmid = %d\n",shmid);
}
return 0;
}
下面演示为什么要这样做
#include<stdio.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<string.h>
int main()
{
// int shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);
int shmid = shmget((key_t)1234,0,0);
if(shmid > 0)
{
shmctl(shmid,IPC_RMID,0);
}
shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);
void *ptr = shmat(shmid,NULL,0);
memcpy(ptr,"helloworld",strlen("helloworld"));
printf("shmid = %d\n",shmid);
return 0;
}
先注释掉第一段代码是最开始实现的开辟共享内存,剩下的是第二种方法实现开辟共享内存,我们运行程序,不会出错
当我们把第一段代码释放掉,下面实现的第二种方法注释起来
#include<stdio.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<string.h>
int main()
{
int shmid = shmget((key_t)1234,4096,IPC_CREAT|0766);
//int shmid = shmget((key_t)1234,0,0);
//if(shmid > 0)
//{
// shmctl(shmid,IPC_RMID,0);
//}
// shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);
void *ptr = shmat(shmid,NULL,0);
memcpy(ptr,"helloworld",strlen("helloworld"));
printf("shmid = %d\n",shmid);
return 0;
}
出现以下结果:
我们来分析一下,仔细看红色的那一段代码,我们把开辟的内存开辟成4096,当我们之前的内存没有清掉,此时我们使用共享内存是一样的,但是开辟出来更大的空间,此时使用shmat映射逻辑地址就会出现段错误。
所以当我们进行服务器开发的时候,如果同组成员之前开辟了共享内存ID为1234,而我们后面也开辟了ID为1234的共享内存,但是我们不知道他开辟了多大,如果一旦开辟不一样大,进行映射逻辑地址的时候就会出错。避免这样的事情发生,我们在开辟共享内存之前,对共享内存进行删除,再进行创建,就会避免这样的事情发生。