[转载]linux内存映射mmap原理分析

转自:http://blog.csdn.net/yusiguyuan/article/details/23388771

 

内存映射,简而言之就是将用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,同样,内核空间对这段区域的修改也直接反映用户空间。那么对于内核空间<---->用户空间两者之间需要大量数据传输等操作的话效率是非常高的。

以下是一个把普遍文件映射到用户空间的内存区域的示意图。
图一:
二、基本函数
    mmap函数是unix/linux下的系统调用,详细内容可参考《Unix Netword programming》卷二12.2节。
mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。
          mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。mmap并不分配空间, 只是将文件映射到调用进程的地址空间里(但是会占掉你的 virutal memory), 然后你就可以用memcpy等操作写文件, 而不用write()了.写完后,内存中的内容并不会立即更新到文件中,而是有一段时间的延迟,你可以调用msync()来显式同步一下, 这样你所写的内容就能立即保存到文件里了.这点应该和驱动相关。 不过通过mmap来写文件这种方式没办法增加文件的长度, 因为要映射的长度在调用mmap()的时候就决定了.如果想取消内存映射,可以调用munmap()来取消内存映射
void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)

mmap用于把文件映射到内存空间中,简单说mmap就是把一个文件的内容在内存里面做一个映像。映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,同样,内核空间对这段区域的修改也直接反映用户空间。那么对于内核空间<---->用户空间两者之间需要大量数据传输等操作的话效率是非常高的。

 

 

原理

首先,“映射”这个词,就和数学课上说的“一一映射”是一个意思,就是建立一种一一对应关系,在这里主要是只 硬盘上文件 的位置与进程 逻辑地址空间 中一块大小相同的区域之间的一一对应,如图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的两到三倍。

 

  1 #include<unistd.h>
  2 
  3 #include<stdio.h>
  4 
  5 #include<stdlib.h>
  6 
  7 #include<string.h>
  8 
  9 #include<sys/types.h>
 10 
 11 #include<sys/stat.h>
 12 
 13 #include<sys/time.h>
 14 
 15 #include<fcntl.h>
 16 
 17 #include<sys/mman.h>
 18 
 19  
 20 
 21 #define MAX 10000
 22 
 23  
 24 
 25 int main()
 26 
 27 {
 28 
 29 int i=0;
 30 
 31 int count=0, fd=0;
 32 
 33 struct timeval tv1, tv2;
 34 
 35 int *array = (int *)malloc( sizeof(int)*MAX );
 36 
 37  
 38 
 39 /*read*/
 40 
 41  
 42 
 43 gettimeofday( &tv1, NULL );
 44 
 45 fd = open( "mmap_test", O_RDWR );
 46 
 47 if( sizeof(int)*MAX != read( fd, (void *)array, sizeof(int)*MAX ) )
 48 
 49 {
 50 
 51 printf( "Reading data failed.../n" );
 52 
 53 return -1;
 54 
 55 }
 56 
 57 for( i=0; i<MAX; ++i )
 58 
 59  
 60 
 61 ++array[ i ];
 62 
 63 if( sizeof(int)*MAX != write( fd, (void *)array, sizeof(int)*MAX ) )
 64 
 65 {
 66 
 67 printf( "Writing data failed.../n" );
 68 
 69 return -1;
 70 
 71 }
 72 
 73 free( array );
 74 
 75 close( fd );
 76 
 77 gettimeofday( &tv2, NULL );
 78 
 79 printf( "Time of read/write: %dms/n", tv2.tv_usec-tv1.tv_usec );
 80 
 81  
 82 
 83 /*mmap*/
 84 
 85  
 86 
 87 gettimeofday( &tv1, NULL );
 88 
 89 fd = open( "mmap_test", O_RDWR );
 90 
 91 array = mmap( NULL, sizeof(int)*MAX, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
 92 
 93 for( i=0; i<MAX; ++i )
 94 
 95  
 96 
 97 ++array[ i ];
 98 
 99 munmap( array, sizeof(int)*MAX );
100 
101 msync( array, sizeof(int)*MAX, MS_SYNC );
102 
103 free( array );
104 
105 close( fd );
106 
107 gettimeofday( &tv2, NULL );
108 
109 printf( "Time of mmap: %dms/n", tv2.tv_usec-tv1.tv_usec );
110 
111  
112 
113 return 0;
114 
115 }

 

输出结果:

Time of read/write: 154msTime of mmap: 68ms

 

转载于:https://www.cnblogs.com/wanpengcoder/articles/5306688.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396525.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

冒泡、快速排序小结

1.冒泡排序 (1) 比较领近的两个数 (2) 如果左边的比右边的数字大&#xff0c;则交换位置 (3) 向右移动一位&#xff0c;继续比较相邻的两个数 排序示例&#xff1a; 一轮排序结束后&#xff0c;最大值的位置已经移动最右端&#xff0c;再次如此循环&#xff0c;最终经过n-1次则…

synchronized 异常_由浅入深,Java 并发编程中的 Synchronized

synchronized 作用synchronized 关键字是 Java 并发编程中线程同步的常用手段之一。1.1 作用&#xff1a;确保线程互斥的访问同步代&#xff0c;锁自动释放&#xff0c;多个线程操作同个代码块或函数必须排队获得锁&#xff0c;保证共享变量的修改能够及时可见&#xff0c;获得…

Linux内存分配机制之伙伴系统和SLAB

转载请注明原文地址&#xff1a;http://www.cnblogs.com/ygj0930/p/6539590.html 内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下&#xff0c;避免碎片的产生。这就要求内核采取灵活而恰当的内存分配策略。通常&#xff0c;内存分配一般有两种情况&#xff1a…

this.$modal.confirm 自定义按钮关闭_自定义函数,让你玩转Excel得心应手

让“自动更正”输入统一的文本&#xff0c;你是不是经常为输入某些固定的文本,如《电脑报》而烦恼呢?那就往下看吧。1.执行“工具→自动更正”命令,打开“自动更正”对话框。2.在“替换”下面的方框中输入“pcw”(也可以是其他字符,“pcw”用小写),在“替换为”下面的方框中输…

CCF-CSP 最大的矩形

问题描述在横轴上放了n个相邻的矩形&#xff0c;每个矩形的宽度是1&#xff0c;而第i&#xff08;1 ≤ i ≤ n&#xff09;个矩形的高度是hi。这n个矩形构成了一个直方图。例如&#xff0c;下图中六个矩形的高度就分别是3, 1, 6, 5, 2, 3。请找出能放在给定直方图里面积最大的矩…

MySQL的主从复制云栖社区_MySQL-主从复制

前言前篇说了作为运维在数据库块最起码要会两大技能&#xff0c;今天来说说第二技能--主从复制随着业务的增长&#xff0c;一台数据库服务器以满足不了需求了&#xff0c;负载过重&#xff0c;这时候就需要减压&#xff0c;实现负载均衡读写分离&#xff0c;一主一从或一主多从…

mysql 数据分析的步骤_数据分析8个主要步骤

# 在对数据进行分析时&#xff0c;主要细分为明确目标、应用思维和如下8个具体步骤&#xff1a;1、读取数据2、清洗数据3、操作数据4、转换数据5、整理数据6、分析数据7、展现数据8、总结报告接下来将介绍使用python来具体处理数据&#xff0c;包括上面几个步骤的实现&#xff…

一、win7下安装yii2

作者&#xff1a;PHP学习网 出处&#xff1a;http://www.viphper.com/?p1159 本文版权归作者&#xff0c;欢迎转载&#xff0c;但未经作者同意必须保留此段声明&#xff0c;且在文章页面明显位置给出原文连接&#xff0c;否则保留追究法律责任的权利。 之前在liunx上安装过yii…

vs dll必须和exe在同一个目录_Win10系统丢失 .dll 文件的三种解决方案教程

有时候开机或打开一个软件时&#xff0c;系统会提示无法启动程序&#xff0c;这是怎么回事呢&#xff1f;这是因为计算机丢失某个或某些dll文件&#xff0c;由于系统本身不存在这些运行库文件&#xff0c;需要进行添加才能使用该软件。方法一&#xff1a;下载丢失的.dll文件&am…

datagrid页面获取表单一条数据的例子

【问题背景】 最近在做ITOO考评的时候想从页面获取表单选中的数据&#xff1a; 【代码】 在数据网格&#xff08;datagrid&#xff09;组件包含两种方法来检索选中行数据&#xff1a; getSelected&#xff1a;取得第一个选中行数据&#xff0c;如果没有选中行&#xff0c;则返回…

Spring+SpringMVC+MyBatis+easyUI整合基础篇(十)SVN搭建

前言 前面一篇文章讲了一下版本控制&#xff0c;但其实这一篇并没有打算讲细节的&#xff0c;感觉应该自己去动手弄一下&#xff0c;后来考虑了一下&#xff0c;版本控制真的挺重要的&#xff0c;如果自己实在搭建不好反而不去使用的话&#xff0c;真的有点可惜&#xff0c;当然…

串口数据波形显示_【专题教程第6期】SEGGER的J-Scope波形上位机软件,RTT模式波形上传可飙到500KB/S...

【专题教程第6期】SEGGER的J-Scope波形上位机软件&#xff0c;RTT模式波形上传速度可狂飙到500KB/S左右说明&#xff1a;1、在实际项目中&#xff0c;很多时候&#xff0c;我们需要将传感器或者ADC的数值以波形的形式显示。通常的解决办法是用串口上位机&#xff0c;USB接口上位…

JavaScript-基础入门.0014.JavaScript内置对象

2019独角兽企业重金招聘Python工程师标准>>> 简单介绍: 说明: 内置对象就是不依赖宿主环境在程序执行之前已经存在的对象,不必显式的实例化内置对象,前面已经介绍了大部分内置对象,而Global和Math两个单体内置对象比较特殊,所以单独讲. Global对象: 说明: Js中不属于…

Java中字符串连接符(+)和append的区别

参考链接&#xff1a;https://www.jianshu.com/p/849f1d443b3a 文章结构&#xff1a; 第一部分&#xff1a;对的原理进行分析 第二部分&#xff1a; 和 append 循环对比&#xff08;贴出代码&#xff0c;以及分别循环后的反编译字节码&#xff0c;来对两者进行对比&#xff09;…

百度seo排名点击器_SEO整站优化思路 - 百度seo排名点击

原出处&#xff1a;超级排名系统原文链接&#xff1a;SEO整站优化思路 - 超级排名系统整站优化的大体思路包括哪些&#xff1f;下面超级排名系统小编详细给大家讲解下&#xff1a;一、建站优化我们在建立网站之前与建立网站的时候需要做的优化&#xff0c;包括标题优化、描述关…

unity 天空盒_Unity自定义可编程渲染管线(SRP)(二)——编写第一个自定义SRP

一句话描述&#xff0c;我们可以把SRP分解成两个部分&#xff0c;分别是SRP Asset&#xff0c;SRP Instance。SRP AssetSRP Asset是一个Unity Asset文件&#xff0c;用来存储渲染管线的特定配置信息&#xff0c;包含的信息有&#xff1a;游戏物体是否应该投射阴影&#xff1b;使…

【design pattern】工厂方法模式和抽象工厂模式

前言 设计模式分为三大类&#xff1a; 创建型模式&#xff1a;工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式&#xff1b; 结构型模式&#xff1a;适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式&#xff1b; 行为型模式&#xff1…

弹簧触摸开关原理图_10年老电工经验之谈:常见的开关电源那些事儿

随着电控系统中对控制回路安全性要求提高&#xff0c;控制回路的工作电压是越来越趋于直流低压化。由此&#xff0c;控制回路内各种使用直流电源的传感器、中小微型直流继电器等电器装置是日益增多。也正因如此&#xff0c;电控系统内不同品牌的开关电源也相应地多了起来。因牵…

erlang mysql连接超时_Erlang数据库-(一)Erlang与Mysql的连接

下载&#xff1a;http://download.csdn.net/detail/hjhjava/7088277把该文件的东西全部编译好&#xff0c;然后根据下面的解释就可以操作Mysql的。很简单~-record(row,{a1 0, a20}).%% 第一个参数是该链接的名字(根据它来操作Mysql)&#xff0c;第二参数是本机号(ip地址)%% &a…

管理活动目录域服务实训_管理学院学生党支部开展实践教育基地服务活动

红星E校有态度 有温度 可关注为进一步加强党的建设&#xff0c;深化管理学院学生党支部与实践基地的互动性&#xff0c;2020年9月11至12日&#xff0c;管理学院学生党支部协助白鹤村村委实践基地完成第七次人口普查相关工作&#xff0c;共计6名预备党员参与。工作开始前的培训会…