mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存,但并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。
-----------------------------------------------------------------------------------------------
#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多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去。
-----------------------------------------------------------------------------------------
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 /n 0000006
现在用如下程序操作这个文件
#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
因篇幅问题不能全部显示,请点此查看更多更全内容