*mmap*, 从函数名就可以看出来这是<font color=steelblue> memory map</font>, 即地址的映射, 是一种内存映射文件的方法。(其他的还有 mmap() 系统调用,Posix 共享内存,以及系统 V 共享内存)
-
优点:使用 mmap 方式获取磁盘上的文件信息,只需要将磁盘上的数据拷贝至那块共享内存(内核空间和用户空间共享)中去,用户进程可以直接获取到信息,而相对于传统的 write/read IO 系统调用,必须先把数据从磁盘拷贝至到内核缓冲区中 (页缓冲),然后再把数据拷贝至用户进程中。两者相比,mmap 会少一次拷贝数据,这样带来的性能提升是巨大的(一方面是节省了一次传输,另一方面节省了由于共享空间节省了内存)
-
使用规则:
#include <sys/mman.h>
void *mmap (void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- 参数含义:
- addr 指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。
- length 是映射到调用进程地址空间的字节数,它从被映射文件开头 offset 个字节开始算起。
- prot 参数指定共享内存的访问权限。可取如下几个值的或:PROT_READ(可读) , PROT_WRITE (可写), PROT_EXEC (可执行), PROT_NONE(不可访问)。
- flags 由以下几个常值指定:MAP_SHARED , MAP_PRIVATE , MAP_FIXED,其中,MAP_SHARED , MAP_PRIVATE 必选其一,而 MAP_FIXED 则不推荐使用。offset 参数一般设为 0,表示从文件头开始映射。
- fd 为即将映射到进程空间的文件描述字,一般由 open() 返回,同时,fd 可以指定为 - 1,此时须指定 flags 参数中的 MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信)。
- offset 参数一般设为 0,表示从文件头开始映射, 代表偏移量。
函数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。
- 运用:
- 基于文件的映射
...
fd = open (name, flag, mode);
if(fd<0)
{
printf("error!\n");
}
/* 这块内存可读可写可执行 */
ptr = mmap(NULL, len , PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED , fd , 0);
- 匿名映射(匿名映射是一种没用对应文件的一种映射,是使用特殊文件提供的匿名内存映射)
/* 例如一些网络套接字进行共享*/
ptr = mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0);
pid = fork();
switch (pid)
{
case pid < 0:
printf ("err\n");
case pid = 0: /* 使用互斥的方式访问共享内存 */
lock(ptr)
//修改数据;
unlock(ptr);
case pid > 0: /* 使用互斥的方式访问共享内存 */
lock(ptr)
//修改数据;
unlock(ptr);
}