现在的位置: 首页 > 综合 > 正文

mmap详解

2013年05月01日 ⁄ 综合 ⁄ 共 2096字 ⁄ 字号 评论关闭

mmap函数是unix/linux下的系统调用,来看《Unix Netword programming》卷二12.2节有详细介绍。

mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。
          mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。mmap并不分配空间, 只是将文件映射到调用进程的地址空间里, 然后你就可以用memcpy等操作写文件, 而不用write()了.写完后用msync()同步一下, 你所写的内容就保存到文件里了. 不过这种方式没办法增加文件的长度, 因为要映射的长度在调用mmap()的时候就决定了.

简单说就是把一个文件的内容在内存里面做一个映像,内存比磁盘快些。
基本上它是把一个档案对应到你的virtual memory 中的一段,并传回一个指针。

以后对这段 memory 做存取时,其实就是对那个档做存取。
它就是一种快速 file I/O 的东东,而且使用上和存取 memory 一样方便,只不过会占掉你的 virutal memory。
#include <sys/types.h>
#include <sys/stat.h> //文件状态结构
#include <unistd.h>
#include <sys/mman.h> //mmap头文件

void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);

mmap开启记忆体对映。

参数fd为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信)。

len是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。

 prot参数指定共享内存的访问权限。可取如下几个值的或:PROT_READ(可读),PROT_WRITE(可写),PROT_EXEC(可执行),PROT_NONE(不可访问)。

flags由以下几个常值指定:MAP_SHARED, MAP_PRIVATE, MAP_FIXED。其中,MAP_SHARED,MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。 如果指定为MAP_SHARED,则对映射的内存所做的修改同样影响到文件。如果是MAP_PRIVATE,则对映射的内存所做的修改仅对该进程可见,对文件没有影响。

offset参数一般设为0,表示从文件头开始映射。

int munmap(void *start, size_t length);

int msync(const void *start, size_t length, int flags);
如果开启记忆体对映是希望写入档案中,那麽修改过的记忆体会在一段时间内与档案稍稍有点不同。如果您希望立即将资料写入档案中,可使用msync。
start为记忆体开始位置,length为长度。
flags则有三个:
MS_ASYNC : 请Kernel快将资料写入。
MS_SYNC : 在msync结束返回前,将资料写入。
MS_INVALIDATE : 让核心自行决定是否写入,仅在特殊状况下使用

 

例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

int main()
{
 int fd;
 if ( (fd = open("./file", O_RDWR|O_CREAT, S_IRWXU)) < 0){
  printf("open file wrong!");
  exit(1);
 }
 
 struct stat file_stat;
 if ( fstat( fd, &file_stat) < 0 )
 {
  printf(" fstat wrong");
  exit(1);
 }

 

 void *start_fp;
 if( ( start_fp = mmap(NULL, file_stat.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 )) == MAP_FAILED)
 {
  printf("mmap wrong");
  exit(0);
 }

  snprintf( (char *)start_fp, 4, "test");
  msync( start_fp, file_stat.st_size, MS_ASYNC);

  if ( munmap( start_fp, file_stat.st_size ) < 0 )
  {
  printf("munmap wrong");
  exit(1);
  }

}

抱歉!评论已关闭.