共享内存
原理:
在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(Addr Space),并且都有一个与之对应的页表,负责将进程的虚拟地址与物理地址进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存。
最快的IPC形式,这样的内存区域映射到共享它的进程的地址空间,这些进程的数据传输就不再涉及内核(进程不再通过任何进入内核的系统调用来彼此传递数据,内核必须允许各个进程共享内存区域的内存映射关系然后一直处理该内存区域),但是在共享内存中存放或读取信息需要进程间的同步方式。
客户——服务器交互信息的步骤
使用共享内存方式:(共享内存区对象同时出现在客户和服务器的地址空间中)
- 服务器使用一个信号量来获取某个共享内存对象的权利
- 服务器将数据从输入文件读到共享内存区对象,read的第二个参数指定的数据缓冲区地址指向这个共享内存区对象
- 服务区器读入完毕使用一个信号量通知客户
- 客户将这些数据从该共享内存区对象写到输出文件中
mmap
mmap函数把一个文件或Posix共享内存区对象映射到调用进程的地址空间
- 使用普通文件以提供内存映射I/O
- 使用普通文件以提供匿名内存映射
- 使用sem_open以提供无亲缘关系进程间的Posix共享内存区
#include <sys/mman.h> void *mmap(void *addr,size_t len,int port,int flags,int fd,off_t offset); //返回值:成功返回被映射区的起始地址,成功调用后fd可关闭,该操作对mmap建立映射关系无影响,失败返回MAP_FAILED
- addr:指定描述fd被映射到的进程内空间的起始地址,通常为空指针,让内核自己去选择起始地址,无论哪种情况下返回值都是描述符fd所映射到内存的起始地址
- len:映射到调用进程地址空间的字节数,他被映射文件开头起第offset个字节处开始算,offest通常为0
- port:内存映射保护;PROT_READ:数据可读;PROT_WEITE:数据可写;PROT_EXEC:数据可执行;PROT_NONE:数据不可访问
- flags:MAP_SHARED:变动自私的,调用进程对被映射数据所修改只对改进程可见,而不改变其底层支持对象(或是一个文件对象或是一个共享内存区对象);MAP_SHARED:变动共享的,调用进程对被映射数据所修改对于共享该对象所有的进程可见,改变其底层支持对象(或是一个文件对象或是一个共享内存区对象)——(这二者必须指定一个);MAP_FIXED:准备解释addr参数,从移植方面来讲不应该指定该标志,但addr不是一个空指针,那么addr如何处置取决于实现,不为空的addr值通常被当作有关该内存区应是如何具体定位的线索,可移植性应该把addr指定一个空指针而且不指定MAP_FIXED
munmap
#include <sys/mman.h> int munmap(void *addr,size_t len); //返回值:成功返回0,出错返回-1
- addr:由mmap返回的地址
- len:映射区大小
- 再次访问这些地址将会导致SIGSEGV信号,如果被映射区域是MAP_PRIVATE标志,那么调用进程对他的所有变动都会被丢弃
msync
内核的虚拟内存算法保持映射文件(一般在硬盘上)与内存映射区(一般在内存中)的同步,前提他是一个MAP_SHARED内存区,也就是我们改了处于内存映射到某个文件的内存区中某个位置的内容,那么内核将在稍后某个时刻相应的更新文件,然而我们需要确信硬盘上的文件内容与内存区中的内容一致,于是调用该函数来执行同步
#include <sys/mman.h> int msync(void *addr,size_t len,int flags); //返回值:成功返回0,出错返回-1
flags:
- MS_ASYNC:执行异步写,一旦写操作已由内核排入队列,该标志指定的函数立即返回
- MS_SYNC:执行同步写(与ASYNC选其一,不能同时指定),该标志是等到写操作完成后再返回
- MS_INVALIDATE:使高速缓存的数据丢失,与其最终副本不一致的文件数据的所有内存中副本都失效,后续的引用将从文件中取得数据

更多精彩