mmap共享内存

来源:互联网 发布:python 将list拆分 编辑:程序博客网 时间:2024/06/04 23:36


mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存,但并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。


mmap把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要read/write函数。

-----------------------------------------------------------------------------------------------

 

#include <sys/mman.h> void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off); int munmap(void *addr, size_t len);
------------------------------------------------------------------------------------------------
参数说明:
1.addr,若addr==NULL,内核会自己在进程地址空间中选择合适的地址建立映射。如果addr不是NULL,则给内核一个提示应该从什么地址开始映射,
内核会选择addr之上的某个合适的地址开始映射。建立映射后,真正的映射首地址通过返回值可以得到。
2.len,需要映射的那一部分文件的长度,这也就决定了mmap没办法增加文件的长度。
3.off,表示从文件的什么位置开始映射,必须是页大小的整数倍(在32位体系统结构上通常是4K)。
4.filedes是代表该文件的描述符。
5.prot参数有四种取值:

 

  • PROT_EXEC表示映射的这一段可执行,例如映射共享库

  • PROT_READ表示映射的这一段可读

  • PROT_WRITE表示映射的这一段可写

  • PROT_NONE表示映射的这一段不可访问



6.flag参数有很多种取值

 

  • MAP_SHARED多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修改,另一个进程也会看到这种变化。

  • MAP_PRIVATE多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去。
     




如果mmap成功则返回映射首地址,如果出错则返回常数MAP_FAILED。当进程终止时,该进程的映射内存会自动解除,也可以调用munmap解除映射。munmap成功返回0,出错返回-1。

-----------------------------------------------------------------------------------------

int msync(const void *start, size_t length, int flags); 

-----------------------------------------------------------------------------------------
如果开启记忆体对映是希望写入档案中,那麽修改过的记忆体会在一段时间内与档案稍稍有点不同。如果您希望立即将资料写入档案中,可使用msync。 

start为记忆体开始位置,length为长度。 

flags则有三个: 
MS_ASYNC : 请Kernel快将资料写入。 
MS_SYNC : 在msync结束返回前,将资料写入。 
MS_INVALIDATE : 让核心自行决定是否写入,仅在特殊状况下使用。


一个简单的实验:


$ vi hello(编辑该文件的内容为“hello”)$ od -tx1 -tc hello 0000000 68 65 6c 6c 6f 0a          h   e   l   l   o  /n0000006

现在用如下程序操作这个文件

#include <stdlib.h>#include <sys/mman.h>#include <fcntl.h>int main(void){int *p;int fd = open("hello", O_RDWR);if (fd < 0) {perror("open hello");exit(1);}p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0);if (p == MAP_FAILED) {perror("mmap");exit(1);}close(fd);p[0] = 0x30313233;munmap(p, 6);return 0;}

然后再查看这个文件的内容:

$ od -tx1 -tc hello 0000000 33 32 31 30 6f 0a           3   2   1   0   o  /n 0000006

原创粉丝点击