1.共享内存
共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。
2.共享内存示意图
3.用管道或者消息队列传递数据
4.用共享内存传递数据
5.mmap函数
(1)功能:将文件或者设备空间映射到共享内存区
(2)原型:void* mmap(void* addr, size_t len, int porrt, int flags, int fd, off_t offset);
(3)参数:addr:要映射的起始地址,通常指定为NULL,让内核自动选择
len:映射到进程地址空间的字节数
prot:映射区保护方式
flags:标志
fd:文件描述符
offset:从文件头开始的偏移量
(4)返回值:成功返回映射的内存的起始地址:失败返回-1
6.munmap函数
(1)功能:取消mmap函数建立的映射
(2)原型:int munmap(void* addr, size_t len);
(3)参数:addr:映射的内存起始地址
len:映射到进程地址空间的字节数
(4)返回值:成功返回0;失败返回-1
7.msync函数
(1)功能:对映射的共享内存执行同步操作
(2)原型:int msync(void* addr, size_t len, int flags);
(3)参数:addr:内存起始地址
len:长度
flags:选项
(4)返回值:成功返回0;失败返回-1
8.map注意点
(1)内存映射不能(也不可能)改变文件的大小;
(2)可用于进程间通信的有效地址空间不完全受限于映射文件的大小, 而应该以内存页面的大小为准(见下面测试);
(3)文件一旦被映射之后, 所有对映射区域的访问实际上是对内存区域的访问; 映射区域内容写会文件时, 所写内容不能超过文件的大小。
9.示例
./write执行sleep(10),./read在sleep(10)之内
sleep(10)之外
./write test
./read test
mmap_write.cpp
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.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, "Usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
}
int fd;
fd = open(argv[1], O_CREAT | O_RDWR | O_TRUNC, 0666);
if(-1 == fd) {
ERR_EXIT("open");
}
lseek(fd, sizeof(STU)*5-1, SEEK_SET);;
write(fd, "", 1);
STU* p;
p = (STU*)mmap(NULL, sizeof(STU)*10-1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(NULL == p) {
ERR_EXIT("mmap");
}
char ch = 'a';
int i;
for(i=0; i<10; i++) {
memcpy((p+i)->name, &ch, 1);
(p+i)->age = 20+i;
ch++;
}
printf("initialize over\n");
sleep(10);
munmap(p, sizeof(STU)*10);
printf("exit ...\n");
return 0;
}
mmap_read.cpp
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.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, "Usage: %s <file>\n", argv[1]);
exit(EXIT_FAILURE);
}
int fd;
fd = open(argv[1], O_RDWR);
if(-1 == fd) {
ERR_EXIT("open");
}
STU* p;
p = (STU*)mmap(NULL, sizeof(STU)*10-1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(NULL == p) {
ERR_EXIT("mmap");
}
char ch = 'a';
int i;
for(i=0; i<10; i++) {
printf("name = %s age =%d\n", (p+i)->name, (p+i)->age);
}
munmap(p, sizeof(STU)*10);
printf("exit ...\n");
return 0;
}