1、什么是共享内存
共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它,修改它。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
但有一点特别要注意:共享内存并未提供同步机制。也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问,例如信号量。
2、系统函数详解
(1)获得key值的函数:
key_t ftok(const char *pathname, int proj_id);
(2)申请共享内存函数:
int shmget(key_t key, size_t size, int shmflg); 申请共享内存
错误码:
EINVAL:参数size小于SHMMIN或大于SHMMAX
EEXIST:预建立key所指的共享内存,但已经存在
EIDRM:参数key所指的共享内存已经删除
ENOSPC:超过了系统允许建立的共享内存的最大值(SHMALL)
ENOENT:参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT位
EACCES:没有权限
ENOMEM:核心内存不足
(3)获得共享内存指针:
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数解释:
shmid : 共享内存标识符
shmaddr :指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflg:SHM_RDONLY:为只读模式,其他为读写模式
(4)断开与内存共享的连接:
int shmdt(const void *shmaddr);
shmaddr:连接的共享内存的起始地址
(5)删除共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
cmd参数说明:
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID:删除这片共享内存
3、Linux C代码实现
往共享内存里面写入数据:
#include
#include
#include
#include
#include
#include
#include
#define PRI_SHM_ID 1000
#define PATH_SHM "/home/nii/"
int main()
{
key_t keyVal = 0;
int nShmid = 0;
char *pchShm = NULL;
/* step 1 获得key值 */
keyVal = ftok(PATH_SHM,PRI_SHM_ID);
/** step 2 申请共享内存 */
nShmid = shmget(keyVal,10,IPC_CREAT|0666);
if(nShmid == -1)
{
printf("create share memory failed\n");
return 1;
}
/**step3 申请共享内存指针 */
pchShm = (char*)shmat(nShmid,0,0);
if(NULL == pchShm)
{
printf("get share pointer failed\n");
return 1;
}
/** step4 对该共享指针进行操作,给共享指针赋值 */
strncpy(pchShm,"wang zheng jun",20);
/* step5 释放该共享地址 */
shmdt(pchShm);
/** 删除该块共享内存 */
//shmctl(nShmid,IPC_RMID,NULL);
return 0;
}
读取共享内存的数据:
#include
#include
#include
#include
#include
#include
#include
#define PRI_SHM_ID 1000
#define PATH_SHM "/home/nii/"
int main()
{
key_t keyVal = 0;
int nShmid = 0;
char *pchShm = NULL;
/* step 1 获得key值 */
keyVal = ftok(PATH_SHM,PRI_SHM_ID);
/** step 2 申请共享内存 */
nShmid = shmget(keyVal,10,IPC_CREAT|0666);
if(nShmid == -1)
{
printf("create share memory failed\n");
return 1;
}
/**step3 申请共享内存指针 */
pchShm = (char*)shmat(nShmid,0,0);
if(NULL == pchShm)
{
printf("get share pointer failed\n");
return 1;
}
/** step4 对该共享指针进行操作 */
printf("%s\n",pchShm);
/* step5 释放该共享地址 */
shmdt(pchShm);
/** 删除该块共享内存,一般情况下不要删除该共享内存 */
//shmctl(nShmid,IPC_RMID,NULL);
return 0;
}