1.概述:
1.共享内存区是可用IPC形式中最快的。
2.一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传递就不再涉及内核
“不再涉及内核“的含义:进程不再通过执行任何进入内核的系统调用来彼此传递数据。显然,内核必须建立允许各个进程共享该内存区的内存映射关系,然后一直管理该内存区(处理页故障等)
管道,FIFO和消息队列的问题在于,两个进程要交换信息时,这些信息必须经由内核传递。
2.mmap、munmap和msync函数
1.mmap函数把一个**文件**或一个**Posix共享内存区对象**映射到调用进程的地址空间。使用该函数有三个目的:
(1)使用普通文件以提供内存映射I/O
(2)使用特殊文件以提供匿名内存映射
(3)使用shm_open以提供无亲缘关系进程间的Posix共享内存区
#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
返回:若成功则为被映射区的起始地址,若出错则为MAP_FAILED
addr:指定描述符fd应被映射到的进程内空间的起始地址。通常为NULL,这样让内核自己去选择起始地址。
len:映射到调用进程地址空间中的字节数,它从被映射文件开头起第offset个字节处开始算。offset通常为0.
prot:内存映射区的保护。常见的值是代表读写访问的PROT_READ|PROT_WRITE
PROT_READ 数据可读
PROT_WRITE 数据可写
PROT_EXEC 数据可执行
PROT_NONE 数据不可访问
flag:MAP_SHARED和MAP_PRIVATE这两个标志必须指定一个。
MAP_SHARED 变动是共享的
MAP_PRIVATE 变动是私有的
mmap成功返回后,fd参数可以关闭。该操作对由于mmap建立的映射关系没有影响
#include <sys/mman.h>
int munmap(void *addr, size_t len);
返回:若成功则返回0,若出错则为-1
addr:由mmap返回的地址
len:映射区的大小
#include <sys/mman.h>
int msync(void *addr, size_t len, int flags);
返回:若成功则返回0,若出错则为-1
flag:MS_ASYNC和MS_SYNC必须指定一个
MS_ASYNC 执行异步写
MS_SYNC 执行同步写
MS_INVALIDATE 使高速缓存的数据失效
为何使用mmap?
内存映射文件:open后调用mmap把它映射到调用进程地址空间的某个文件
通过使用内存映射文件得到的特性:
1.简化操作
所有的I/O都在内核的掩盖下完成,我们只需编写存取内存映射区中各个值的代码(绝不调用read,write,lseek)
2.在无亲缘关系的进程间提供共享的内存区
所映射文件的实际内容成了被共享内存区的初始内容,而且这些进程对该共享内存区所做的任何变动都复制回所映射的文件