内存映射文件详解-程序员宅基地

技术标签: 内存映射文件  

http://blog.csdn.net/mg0832058/article/details/5890688

一直都对内存映射文件这个概念很模糊,不知道它和虚拟内存有什么区别,而且映射这个词也很让人迷茫,今天终于搞清楚了。。。下面,我先解释一下我对映射这个词的理解,再区分一下几个容易混淆的概念,之后,什么是内存映射就很明朗了。

原理
首先,“映射”这个词,就和数学课上说的“一一映射”是一个意思,就是建立一种一一对应关系,在这里主要是只 硬盘上文件 的位置与进程 逻辑地址空间 中 一块大小相同的区域之间的一一对应,如图1中过程1所示。这种对应关系纯属是逻辑上的概念,物理上是不存在的,原因是进程的逻辑地址空间本身就是不存在 的。在内存映射的过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上被放入了内存,具体到代码,就是建立并初始化了相关的数据结构 (struct address_space),这个过程有系统调用mmap()实现,所以建立内存映射的效率很高。
这里写图片描述
图1.内存映射原理

既然建立内存映射没有进行实际的数据拷贝,那么进程又怎么能最终直接通过内存操作访问到硬盘上的文件呢?那就要看内存映射之后的几个相关的过程了。

mmap()会 返回一个指针ptr,它指向进程逻辑地址空间中的一个地址,这样以后,进程无需再调用read或write对文件进行读写,而只需要通过ptr就能够操作 文件。但是ptr所指向的是一个逻辑地址,要操作其中的数据,必须通过MMU将逻辑地址转换成物理地址,如图1中过程2所示。这个过程与内存映射无关。

前 面讲过,建立内存映射并没有实际拷贝数据,这时,MMU在地址映射表中是无法找到与ptr相对应的物理地址的,也就是MMU失败,将产生一个缺页中断,缺 页中断的中断响应函数会在swap中寻找相对应的页面,如果找不到(也就是该文件从来没有被读入内存的情况),则会通过mmap()建立的映射关系,从硬 盘上将文件读取到物理内存中,如图1中过程3所示。这个过程与内存映射无关。

如果在拷贝数据时,发现物理内存不够用,则会通过虚拟内存机制(swap)将暂时不用的物理页面交换到硬盘上,如图1中过程4所示。这个过程也与内存映射无关。

效率
从 代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一 样的。但是通过内存映射的方法访问硬盘上的文件,效率要比read和write系统调用高,这是为什么呢?原因是read()是系统调用,其中进行了数据 拷贝,它首先将文件内容从硬盘拷贝到内核空间的一个缓冲区,如图2中过程1,然后再将这些数据拷贝到用户空间,如图2中过程2,在这个过程中,实际上完成 了 两次数据拷贝 ;而mmap()也是系统调用,如前所述,mmap()中没有进行数据拷贝,真正的数据拷贝是在缺页中断处理时进行的,由于mmap()将文件直接映射到用户空间,所以中断处理函数根据这个映射关系,直接将文件从硬盘拷贝到用户空间,只进行了 一次数据拷贝 。因此,内存映射的效率要比read/write效率高。

这里写图片描述
图2.read系统调用原理

下面这个程序,通过read和mmap两种方法分别对硬盘上一个名为“mmap_test”的文件进行操作,文件中存有10000个整数,程序两次使用不同的方法将它们读出,加1,再写回硬盘。通过对比可以看出,read消耗的时间将近是mmap的两到三倍。

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define MAX 10000

int main()
{
int i=0;
int count=0, fd=0;
struct timeval tv1, tv2;
int *array = (int *)malloc( sizeof(int)*MAX );

/*read*/

gettimeofday( &tv1, NULL );
fd = open( "mmap_test", O_RDWR );
if( sizeof(int)*MAX != read( fd, (void *)array, sizeof(int)*MAX ) )
{
printf( "Reading data failed.../n" );
return -1;
}
for( i=0; i

++array[ i ];
if( sizeof(int)*MAX != write( fd, (void *)array, sizeof(int)*MAX ) )
{
printf( "Writing data failed.../n" );
return -1;
}
free( array );
close( fd );
gettimeofday( &tv2, NULL );
printf( "Time of read/write: %dms/n", tv2.tv_usec-tv1.tv_usec );

/*mmap*/

gettimeofday( &tv1, NULL );
fd = open( "mmap_test", O_RDWR );
array = mmap( NULL, sizeof(int)*MAX, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
for( i=0; i

++array[ i ];
munmap( array, sizeof(int)*MAX );
msync( array, sizeof(int)*MAX, MS_SYNC );
free( array );
close( fd );
gettimeofday( &tv2, NULL );
printf( "Time of mmap: %dms/n", tv2.tv_usec-tv1.tv_usec );

return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_16467097/article/details/52797837

智能推荐

对于74HC595的简易理解_74hc595简述ser引脚、sck引脚、rck引脚是如何相互配合实现数据传输的:-程序员宅基地

文章浏览阅读224次。对于74HC595的理解_74hc595简述ser引脚、sck引脚、rck引脚是如何相互配合实现数据传输的:

求二叉树的高度并输出,并按树状打印该二叉树_输出二叉树高度代码-程序员宅基地

文章浏览阅读1.1k次。/*补全所给程序3,输出所给二叉树的全部结点,求二叉树的高度并输出,并按树状打印该二叉树*/#include<stdio.h>#include<stdlib.h>typedefcharDataType;typedefstructNode{DataTypedata;structNode*LChild;structNode*RChild;}BiTNode,*BiTree;voidCrea..._输出二叉树高度代码

opencv KNN匹配等方法的解释-程序员宅基地

文章浏览阅读7.5k次,点赞7次,收藏23次。问题描述在学习opencv的KNN匹配时,想查找KNN匹配的机制是什么,但是搜到的都是机器学习里面的分类KNN算法,感觉不是同一个东西,所以感到奇怪。问题解决看到一个帖子解释得很好,mark一下。特征点匹配..._opencv knn匹配

202457读书笔记|《万有可爱日历20241-3》——遇见你真好,花瓣拂过脸颊,仿佛春天温柔的亲吻了我-程序员宅基地

文章浏览阅读126次。万有可爱历2024(1-3月刊·治愈系天花板bibi动物园漫画日历)》bibi园长著绘。不过微读对我真好,送了3天付费会员卡,于是把这本小书看完了,有几幅蛮不错的。话说小林老师的漫画日历我已经有几天没翻了,可我实在太困了,明天再更新吧。爱就是遇见你很好 总想要看见你。看到我推荐这本20241-3月的日历。花瓣拂过脸颊。该怎么形容那种兴奋的感觉呢。付费书籍诶,本来以为看不了。仿佛春天温柔的亲吻了我。

前端八股文-程序员宅基地

文章浏览阅读1.5w次,点赞34次,收藏307次。文章目录一. JavaScript1.1 基本数据类型 (7种)1.2 this 的指向 (new, 隐式绑定, 显式绑定)1.3 call, apply(数组), bind1.4 eventloop, 宏任务和微任务1.5 闭包 (概念, 用途, 手写)1.7 继承 (extends, 原型链继承, 构造函数继承, 组合继承, 寄生组合继承)1.8深拷贝和浅拷贝1.9 PromiseAjax请求过程AMD、CMD、CommonJs、ES6的对比require,import和import()函数的区别ES_前端八股文

手游性能测试指南_手游性能指标-程序员宅基地

文章浏览阅读5k次。随着手游3D类型游戏增多,对机器资源占用越发高,但用户手中硬件的提升是一个不可控且缓慢的过程,为了保证在尽量广泛的机型上流畅运行,提高游戏本身的潜在用户群体,所以手游客户端性能审核工作就越发重要,如何做客户端性能审核,如何快速,专业,准确的做客户端性能审核是我们需要重点关注、且持续建设的内容。_手游性能指标

随便推点

复现 DLink DIR-859 RCE 漏洞(CVE-2019–20215)_d-link dir-859 1.05 and 1.06b01 beta01 devices all-程序员宅基地

文章浏览阅读1.1k次。复现 DLink DIR-859 RCE 漏洞(CVE-2019–20215)漏洞介绍漏洞影响漏洞等级环境搭建模拟攻击漏洞原理解决方案漏洞介绍该漏洞允许远程攻击者通过 urn 执行任意操作系统命令:到 /htdocs/cgibin 中 ssdpcgi()中的 M-SEARCH 方法,因为 REMOTE_PORT 处理不当。urn: service/device 的值使用 strstr 函数进行检查,该函数允许攻击者连接由 shell 元字符分隔的任意命令。漏洞影响D-Link DIR-859 1.0_d-link dir-859 1.05 and 1.06b01 beta01 devices allow remote attackers to exe

Redash详细Docker部署教程_redash docker 部署-程序员宅基地

文章浏览阅读1.9k次。Redash详细部署教程1、安装Docker-CE1.1、安装步骤Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。#检测Linux版本 命令:uname -r[root@mongodb-s..._redash docker 部署

【Apollo】AutoDrive Apollo5.0感知模块学习_感知模块的输出输出交互表,包括topic、消息类型、说明-程序员宅基地

文章浏览阅读2.1k次。源码下载百度的自动驾驶项目Apollo有好几个版本,我目前在学习的是5.0版本。源码是从Github上找的,链接为apollo源码。但是整个项目实在是有些大,就算是我翻墙出去下载也一直显示下载失败。所以我只好先下载其中的perception也就是感知模块先进行学习。但是Github本身是只能下载整个项目的,也是意外的发现了DownGit这个东西,直接把项目中需要下载的文件链接copy到DownG..._感知模块的输出输出交互表,包括topic、消息类型、说明

Unity 无限场景缝隙问题等_unity scroll view viewport与scrollbar vertical中间有缝隙-程序员宅基地

文章浏览阅读2.6k次。!!!! Unity中UI的绘制顺序和它们出现在Hierarchy的顺序是一样的。这也意味着你要调整GUI控件的顺序只要调整它在Hierarchy的顺序就可以了。 继续探究toggleGroup里面的toggle四个toggle在一个组里面1.如果开始全为未选中状态,只要选中一个,则最后依然会只有一个被选中,无法取消2.如果开始(初始状态)多于一个被选中,则,最后一个被点击的为最后一个唯一被选中的..._unity scroll view viewport与scrollbar vertical中间有缝隙

IO扩展芯片应用及方案选型 (74HC595,74HC165,8255,CH351等)_74hc595 支持频率-程序员宅基地

文章浏览阅读841次,点赞17次,收藏16次。在我们进行单片机开发的时候, 经常会发现I/O 口不够用。一方面是因为我们产品中往往都包括很多的功能, 又有显示, 又有存储等等;另一方面是我们所使用的单片机芯片确实I/ O 资源不多。有人说, 你可以选I/O 口比较多的芯片, 比如说把 STM32F103C8T6 换成同型号大封装的, 或者直接换 F407。没错, 如果在成本允许的情况下, 确实是I/O 不够一换了之。但成本往往是需要考虑的首要因素。_74hc595 支持频率

局域网QQ第三版(V1.4)-程序员宅基地

文章浏览阅读2.7k次。局域网QQ,无客户端和服务端之分,局域网的计算机运行本程序就可以互相看见,可以自由聊天和传文件。本版较之1.0版的改进之处: 使用数据结构类型传送数据; 增加传文件功能(有进度条);考_局域网qq

推荐文章

热门文章

相关标签