共享内存mmap()和CreateFileMapping()

共享内存是进程间的一种通信机制,而且它的作用不止于此。它的主要作用包括:提高I/O效率,匿名内存映射,内存共享进程通信。两个不同进程共享内存的意思是,同一快物理内存映射到该两个进程的进程地址空间。使用共享内存可以通过mmap()返回的指针直接操作文件中的内容,省去了read,write以及lseek等文件读写的操作,提高了I/O效率。并且共享内存是一中效率较高的进程间的通信机制,因为当通信建立时,进程在对共享内存的操作的时候,并不是读写少量数据时就解除映射,等有新的通信的时候,在重新建立共享内存的映射;而是一直保持共享内存区域,直到通信完成为止,这样数据一直保存在共享内存区域,并没有写回文件。通常是在解除映射的时候,才会会写回文件。

那么怎样保持多个进程映射到同一个共享内存的内存页面呢?

我们知道虚拟内存的技术,简单的来说就是在真实的物理内存之外再在硬盘空间增加一个交换区(swap),也就是进程地址空间用到的是虚拟内存,多个进程的虚拟内存的总和是大于物理内存的,那么就安装一定的分配方案把暂时不用的虚拟内存对应的物理内存中的数据保存到硬盘中去(也就是swap area),然后将腾出来的物理内存供给有需要的进程使用。虚拟内存和物理内存有一种映射关系,而且他们是以页为单位映射的,并非是逐个字节的映射。当进程调用mmap()时,只是在进程地址空间中产生了一块缓冲区域,并没有建立其到物理内存的映射关系。因此第一访问该空间时,会引发一个缺页异常。

当我们对普通文件进行操作的时候,通常是把它们读入内存中才能对其执行read,write,lseek等操作。当对其建立虚拟内存到物理内存的映射关系时,系统是先查找该文件是否在page cache(当前的物理内存区域中),如果没有找到,就是还没有读入内存,处理程序会从磁盘读入相应的页面,并返回相应的地址,同时,进程页表也会更新。

如果是对与共享内存映射的情况,缺页处理程序会现在page cache中寻找目标页,找到后直接返回相应的地址;如果没有找到,则进入swap cache中寻找目标页,如果找到则执行一个换入操作,并返回相应的地址;如果没有找到,则分配新的物理页面,并把它读入page cache中,更新进程页表。

普通文件的映射和共享内存映射有一个主要的不同点就是后者会查找swap cahe区域中是否存在目标页,这是因为为了让不同进程映射到同一个内存页面,考虑到不同进程的运行中可能把该内存页面换入到swap区域,因此要在swap区域中寻找该目标页,如果创建一个新的物理页面,这样会使不同进程映射到了不同的内存页面。


下面就着重的介绍Linux和Windows下的共享内存如何使用。

Linux下有关共享内存的常用函数有:mmap() ,munmap()以及msync()。

1. mmap()创建共享内存映射

原型:

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 
参数:

返回参数:void指针,它可以为任何类型的指针;是目标页的对应的地址,通过该指针可以对目标页进行操作

addr:指定为文件描述符fd应被映射到的进程空间的起始地址。它通常被指定为一个空指针,这样告诉内核自己去选择起始地址。一般默认为NULL。

length:是映射到调用进程地址空间中的字节数,她从被映射文件开头offset个字节处开始算。

prot:负责保护内存映射区的保护。常用值是代表读写访问的PROT_READ | PROT_WRITE.当然还包括数据的执行(PROT_EXEC)、数据不可访问(PROT_NONE)

flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体
MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。
MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。

该参数还有更多的值,可以参考mmap的手册。

fd:是有效的文件操作符,一般由open()函数返回,也可以指定为-1,映射匿名共享内存,而且需要flags参数中包含MAP_ANONYMOUS

offset:被映射对象内存的起点,一般设置为0;

2. munmap() 解除共享内存映射

#include <sys/mman.h>
int munmap(void *addr, size_t length)
参数:

addr:是由mmap()返回的指针;

length:映射区域的大小

3. msync() 

int mysnc(void *addr, size_t length, int flags)
其作用是为了实现磁盘上文件内容和内存中的内容一致。因为mmap()创建的共享内存区域并不是马上的写回磁盘文件中去的,而是等待调用munmap()或msync()后才会写回文件。

下面是使用mma

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值