Linux下共享内存有mmap和System V两种方式
1.mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。由此看来mmap并不纯粹是为实现共享内存而设计的
2.System V 共享内存是通过映射特殊文件系统 shm 中的文件实现进程间的共享内存通信,即把所有共享数据放在共享内存区域, 任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面。
两者从应用上来看,区别不大,一个是操作普通文件,一个是操作交换分区上的 shm 文件系统
1. mmap方式
写进程:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define SHMNAME "shm_ram"
#define OPEN_FLAG O_RDWR|O_CREAT
#define OPEN_MODE 00777
#define FILE_SIZE 4096*4
int main(int argc,char **argv)
{
int ret = -1;
int fd = -1;
void* add_w = NULL;
//创建或者打开一个共享内存
fd = shm_open(SHMNAME, OPEN_FLAG, OPEN_MODE);
if(-1 == (ret = fd))
{
perror("shm failed: ");
return ret;;
}
//调整确定文件共享内存的空间
ret = ftruncate(fd, FILE_SIZE);
if(-1 == ret)
{
perror("ftruncate");
return ret;;
}
// 映射目标文件的存储区
add_w = mmap(NULL, FILE_SIZE, PROT_WRITE, MAP_SHARED, fd, SEEK_SET);
if(NULL == add_w)
{
perror("mmap");
return ret;;
}
// memcpy 内存共享 写入内容
memcpy(add_w, "howaylee", sizeof("howaylee"));
// 取消映射
ret = munmap(add_w, FILE_SIZE);
if(-1 == ret)
{
perror("munmap add_w faile: ");
return ret;;
}
// 删除内存共享
/*shm_unlink(SHMNAME);
if(-1 == ret)
{
perror("shm_unlink faile: ");
return ret;;
}*/
}
读进程
int main(int argc,char **argv)
{
int ret = -1;
int fd = -1;
char buf[4096] = {0};
void* add_r = NULL;
//创建或者打开一个共享内存
fd = shm_open(SHMNAME, OPEN_FLAG, OPEN_MODE);
if(-1 == (ret = fd))
{
perror("shm");
return ret;
}
//调整确定文件共享内存的空间
ret = ftruncate(fd, FILE_SIZE); // 16k
if(-1 == ret)
{
perror("ftruncate");
return ret;
}
// 映射目标文件的存储区
add_r = mmap(NULL, FILE_SIZE, PROT_READ, MAP_SHARED, fd, SEEK_SET);
if(NULL == add_r)
{
perror("mmap");
return ret;
}
// memcpy 内存共享 写入内容
memcpy(buf, add_r, sizeof(buf));
printf("buf = %s\n", buf);
// 取消映射
ret = munmap(add_r, FILE_SIZE);
if(-1 == ret)
{
perror("munmap");
return ret;
}
}
2. System V方式
system V API比较简洁,只涉及到 shmget(),shmmat(),shmmdt(),shmctrl()四个函数,与信号量函数命名一致
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #define MY_SHM_ID 0x00004589 #define IPC_BUF_SIZE 1*1024*1024 pthread_mutex_t mutex; bool WriteShmMsg(const char *szMsg) { if(pthread_mutex_init(&mutex,NULL)!=0) { printf("错误:初始化锁失败\n"); return false; } // 创建共享内存区 if((shmid=shmget(MY_SHM_ID,IPC_BUF_SIZE,0600|IPC_CREAT))<0) { perror("shmget"); return false; } void *mem; // 映射共享内存区 if((mem=shmat(shmid,0,0))==(void*)-1) { perror("shmat"); return false; } sprintf((char*)mem,"%s",szMsg); // 写入消息 shmdt(mem); // 取消共享内存映射 pthread_mutex_unlock(&mutex); return true; }
更多内容参见:
http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html
http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index2.html