概述:
共享内存是可用IPC形式中最快的。一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据传递就不在涉及内核。然而往该共享内存区存放信息或从中取走信息的进程间需要某种形式的同步。
相关函数:
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
mmap函数把一个文件或一个POSIX共享内存区对象映射到调用进程的地址空间。使用该函数有三个目的:
(1)使用普通文件以提供内存映射I/O;
(2)使用特殊文件以提供匿名内存支持。
(3)使用shm_open以提供无亲缘关系进程间的POSIX共享内存区。
参数说明:
addr:可以指定描述符fd应被映射到进程内空间的起始地址。它通常被指定为一个为空指针,让内核自己选择起始地址。
length:映射到调用进程空间中的字节数,它从被映射文件开头起第offset个字节处开始算。offset通常设置为0。
prot:内存映射区的保护
PROT_READ 数据可读
PROT_WRITE 数据可写
PROT_EXEC 数据可执行
PROT_NONE 数据不可访问
flags:MAP_SHARED或MAP_PRIVATE这两个标志必须指定一个,并可有选择或上MAX_FIXED。
int munmap(void *addr, size_t length);
为从某个进程的地址空间删除一个映射关系,我们调用munmap。其中addr参数是有map返回的地址,len是映射区的大小。
注:参考UNIX网络编程卷2:进程间通信
测试程序:
向共享内存写入数据:
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0); \
typedef struct stu
{
char name[4];
int age;
}STU;
int main(int argc,char *argv[])
{
if (argc != 2)
{
fprintf(stderr,"User:%s <file>\n",argv[0]);
exit(EXIT_FAILURE);
}
int fd;
fd = open(argv[1],O_CREAT | O_RDWR | O_TRUNC, 0666);
if(fd == -1)
ERR_EXIT("open");
lseek(fd,sizeof(STU)*5-1,SEEK_SET);
write(fd,"",1);
STU *p;
p = (STU*)mmap(NULL,sizeof(STU)*5, PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
if(p == (void*)-1)
ERR_EXIT("mmap");
char ch = 'a';
int i = 0;
for(i=0; i<5; i++)
{
memcpy((p+i)->name,&ch,1);
(p+i)->age = 20+i;
ch++;
}
printf("initialize over\n");
munmap(p,sizeof(STU)*5);
printf("exit\n");
return 0;
}
向共享内存读取数据:
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0); \
typedef struct stu
{
char name[4];
int age;
}STU;
int main(int argc,char *argv[])
{
if (argc != 2)
{
fprintf(stderr,"User:%s <file>\n",argv[0]);
exit(EXIT_FAILURE);
}
int fd;
fd = open(argv[1],O_RDWR);
if(fd == -1)
ERR_EXIT("open");
STU *p;
p = (STU*)mmap(NULL,sizeof(STU)*5, PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
if(p == (void*)-1)
ERR_EXIT("mmap");
int i;
for(i=0; i<5; i++)
{
printf("name = %s\nage=%d\n",(p+i)->name,(p+i)->age);
}
munmap(p,sizeof(STU)*5);
printf("exit\n");
return 0;
}