1.使用共享内存一般步骤 :
1.1获得共享内存对象的ID:shmget()
1.2将共享内存映射至本进程虚拟内存空间的某个区域:shmat()
1.3当不适用时,解除映射关系shmdt()
1.4当所有进程都不用共享内存之时,删除共享内存shmctl()
2. 共享内存的创建函数shmget
注意:
参数 key:IPC_PRIVATE 或 ftok的返回值,IPC_PRIVATE会生成相同的key值,ftok生成不同的key值
参数size:申请共享内存的大小 ,第一次申请的共享内存的大小决定了他的上限,并且只要你没有进行过删除这段共享内存的操作,这段共享内存会一直存在。要想申请这段共享内存成功需要确认几点:内存大小比能申请的最小值大且比最大值小,若以该键值申请过共享内存了,之后所申请的内存大小要比第一次开的内存大小要只小不大(同一key值第一申请内存大小为最大,后续要改只能比第一次申请的内存要小,不同key值不影响,不超过申请内存上限就好)。
参数mode:与open函数的mode一样,用来设置内存的权限
要查看共享内存能开的最大最小值的命令是:
cat /proc/sys/kernel/shmmax
cat /proc/sys/kernel/shmmni
然后发现最小值是4096,最大值是18446744073692774399
3.共享内存的映射和解除映射函数
注意:
参数shmid:shmget函数返回值的ID号
参数shmaddr:映射到的地址,NULL为系统自动完成的映射(推荐)
参数shmflg: SHM_RDONLY共享内存只读,默认是0,表示可读写
4.获取或者设置共享内存的相关属性
注意:
当有进程在使用共享内存块时,无法删除共享内存,等待所有进程使用shmdt脱离共享内存映射,才能删除
5.例子:
注意:如果想要两个或多个进程同时使用同一块共享内存,需要fotk(const char *pathname, proj_id)的两个参数一模一样,生成相同的key值,然后用shmget获取共享内存,再用shmat映射共享内存就可以两个进程间访问同一块内存了(在Ubuntu16试过)。
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
int shmid;
int key;
char systemBuf[20] = {0};
char *p = NULL;
key=ftok("./",'b'); //当前进程路径生成key值
if(key <0 )
{
printf("creat key fialure\n");
return -2;
}
printf("creat key sucess key=%X\n",key);
shmid=shmget(key,128,IPC_CREAT | 0777); //生成共享内存,并返回共享内存ID
if(shmid <0)
{
printf("creat share memory failure\n");
return -1;
}
printf("creat share memory sucess shmid=%d\n",shmid);
system("ipcs -m"); //相当于在终端输入命令#ips -m
p=(char *)shmat(shmid,NULL,0); //在本进程内共享内存的映射,映射之后才能在进程中使用,类似于malloc()和数组
if(p == NULL)
{
printf("shmat function failure\n");
return -3;
}
fgets(p,128,stdin); //write share memory
printf("share memory data:%s",p); //start read share memory
printf("second read share memory data:%s",p); //跟管道不同,于数组相同,只要没有将内存清除,数据就不是丢失,读取多少遍都一样
shmdt(p); //删除对共享内存的映射,删除后该进程无法再访问共享内存,但是共享内存还是存在
shmctl(shmid,IPC_RMID,NULL); //删除共享内存,完完全全删除,消息在Linux中
// sprintf(systemBuf, "ipcrm -m %d", shmid); //删除共享内存,完完全全删除,消息在Linux中
// system(systemBuf);
system("ipcs -m");
return 0;
}