什么是 mmap

1. mmap 基础概念

mmap 即 memory map,也就是内存映射。

mmap 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用 read、write 等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。如下图所示:

mmap 具有如下的特点:

    mmap 向应用程序提供的内存访问接口是内存地址连续的,但是对应的磁盘文件的 block 可以不是地址连续的;
    mmap 提供的内存空间是虚拟空间(虚拟内存),而不是物理空间(物理内存),因此完全可以分配远远大于物理内存大小的虚拟空间(例如 16G 内存主机分配 1000G 的 mmap 内存空间);
    mmap 负责映射文件逻辑上一段连续的数据(物理上可以不连续存储)映射为连续内存,而这里的文件可以是磁盘文件、驱动假造出的文件(例如 DMA 技术)以及设备;
    mmap 由操作系统负责管理,对同一个文件地址的映射将被所有线程共享,操作系统确保线程安全以及线程可见性;

mmap 的设计很有启发性。基于磁盘的读写单位是 block(一般大小为 4KB),而基于内存的读写单位是地址(虽然内存的管理与分配单位是 4KB)。换言之,CPU 进行一次磁盘读写操作涉及的数据量至少是 4KB,但是进行一次内存操作涉及的数据量是基于地址的,也就是通常的 64bit(64 位操作系统)。mmap 下进程可以采用指针的方式进行读写操作,这是值得注意的。
2. mmap 的 I/O 模型

mmap 也是一种零拷贝技术,其 I/O 模型如下图所示:

mmap

mmap 技术有如下特点:

    利用 DMA 技术来取代 CPU 来在内存与其他组件之间的数据拷贝,例如从磁盘到内存,从内存到网卡;
    用户空间的 mmap file 使用虚拟内存,实际上并不占据物理内存,只有在内核空间的 kernel buffer cache 才占据实际的物理内存;
    mmap() 函数需要配合 write() 系统调动进行配合操作,这与 sendfile() 函数有所不同,后者一次性代替了 read() 以及 write();因此 mmap 也至少需要 4 次上下文切换;
    mmap 仅仅能够避免内核空间到用户空间的全程 CPU 负责的数据拷贝,但是内核空间内部还是需要全程 CPU 负责的数据拷贝;

利用 mmap() 替换 read(),配合 write() 调用的整个流程如下:

    用户进程调用 mmap(),从用户态陷入内核态,将内核缓冲区映射到用户缓存区;
    DMA 控制器将数据从硬盘拷贝到内核缓冲区(可见其使用了 Page Cache 机制);
    mmap() 返回,上下文从内核态切换回用户态;
    用户进程调用 write(),尝试把文件数据写到内核里的套接字缓冲区,再次陷入内核态;
    CPU 将内核缓冲区中的数据拷贝到的套接字缓冲区;
    DMA 控制器将数据从套接字缓冲区拷贝到网卡完成数据传输;
    write() 返回,上下文从内核态切换回用户态。

3. mmap 的优势

1.简化用户进程编程

在用户空间看来,通过 mmap 机制以后,磁盘上的文件仿佛直接就在内存中,把访问磁盘文件简化为按地址访问内存。这样一来,应用程序自然不需要使用文件系统的 write(写入)、read(读取)、fsync(同步)等系统调用,因为现在只要面向内存的虚拟空间进行开发。

但是,这并不意味着我们不再需要进行这些系统调用,而是说这些系统调用由操作系统在 mmap 机制的内部封装好了。

(1)基于缺页异常的懒加载

出于节约物理内存以及 mmap 方法快速返回的目的,mmap 映射采用懒加载机制。具体来说,通过 mmap 申请 1000G 内存可能仅仅占用了 100MB 的虚拟内存空间,甚至没有分配实际的物理内存空间。当你访问相关内存地址时,才会进行真正的 write、read 等系统调用。CPU 会通过陷入缺页异常的方式来将磁盘上的数据加载到物理内存中,此时才会发生真正的物理内存分配。

(2)数据一致性由 OS 确保

当发生数据修改时,内存出现脏页,与磁盘文件出现不一致。mmap 机制下由操作系统自动完成内存数据落盘(脏页回刷),用户进程通常并不需要手动管理数据落盘。

2.读写效率提高:避免内核空间到用户空间的数据拷贝

简而言之,mmap 被认为快的原因是因为建立了页到用户进程的虚地址空间映射,以读取文件为例,避免了页从内核空间拷贝到用户空间。

3.避免只读操作时的 swap 操作

虚拟内存带来了种种好处,但是一个最大的问题在于所有进程的虚拟内存大小总和可能大于物理内存总大小,因此当操作系统物理内存不够用时,就会把一部分内存 swap 到磁盘上。

在 mmap 下,如果虚拟空间没有发生写操作,那么由于通过 mmap 操作得到的内存数据完全可以通过再次调用 mmap 操作映射文件得到。但是,通过其他方式分配的内存,在没有发生写操作的情况下,操作系统并不知道如何简单地从现有文件中(除非其重新执行一遍应用程序,但是代价很大)恢复内存数据,因此必须将内存 swap 到磁盘上。

4.节约内存

由于用户空间与内核空间实际上共用同一份数据,因此在大文件场景下在实际物理内存占用上有优势。
4. mmap 不是银弹

mmap 不是银弹,这意味着 mmap 也有其缺陷,在相关场景下的性能存在缺陷:

    由于 mmap 使用时必须实现指定好内存映射的大小,因此 mmap 并不适合变长文件;
    如果更新文件的操作很多,mmap 避免两态拷贝的优势就被摊还,最终还是落在了大量的脏页回写及由此引发的随机 I/O 上,所以在随机写很多的情况下,mmap 方式在效率上不一定会比带缓冲区的一般写快;
    读/写小文件(例如 16K 以下的文件),mmap 与通过 read 系统调用相比有着更高的开销与延迟;同时 mmap 的刷盘由系统全权控制,但是在小数据量的情况下由应用本身手动控制更好;
    mmap 受限于操作系统内存大小:例如在 32-bits 的操作系统上,虚拟内存总大小也就 2GB,但由于 mmap 必须要在内存中找到一块连续的地址块,此时你就无法对 4GB 大小的文件完全进行 mmap,在这种情况下你必须分多块分别进行 mmap,但是此时地址内存地址已经不再连续,使用 mmap 的意义大打折扣,而且引入了额外的复杂性;

5. mmap 的适用场景

mmap 的适用场景实际上非常受限,在如下场合下可以选择使用 mmap 机制:

    多个线程以只读的方式同时访问一个文件,这是因为 mmap 机制下多线程共享了同一物理内存空间,因此节约了内存。案例:多个进程可能依赖于同一个动态链接库,利用 mmap 可以实现内存仅仅加载一份动态链接库,多个进程共享此动态链接库。
    mmap 非常适合用于进程间通信,这是因为对同一文件对应的 mmap 分配的物理内存天然多线程共享,并可以依赖于操作系统的同步原语;
    mmap 虽然比 sendfile 等机制多了一次 CPU 全程参与的内存拷贝,但是用户空间与内核空间并不需要数据拷贝,因此在正确使用情况下并不比 sendfile 效率差;
 

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

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

相关文章

最近项目中遇到的一个算法挑战

在企业信息化进程中,各类智能化运算在不断挑战着我们,最近又遇到一个应用,归纳一下需要实现以下算法 //算法设计 /* *计算是否存在值X1,X2,...,Xm,使等式成立 m*X1(m-1)*X2(m-3)*X3...XmE *如果可解,取解集…

c#利用定时器自动备份数据库(mysql)

1:引用dll MySql.Data.dll, MySqlbackup.dll 2:建一个数据连接静态类 public static class mysql{public static string constr "databasetest;Password密码;user IDroot;serverip地址";public static MySqlConnection conn new MySqlConnection(cons…

构建SAN网络存储

实验目的:构建SAN网络存储 实验环境:redhat 5.4三台,scanstorage作为存储服务,IP地址是:192.168.9.79。node1,node2作为客户端测试 实验步骤: 一、配置服务端: 1、添加一块20G的盘 [rootscans…

netnbsp;与nbsp;javascript脚本的几种交互方法

1.asp.net呼叫jsResponse.Write("<scriptlanguagejavascript>");Response.Write("alert(登峰欢迎您 );" );Response.Write("location.hreflogin.aspx;") ;Response.Write("</script>");在这里情况下,你可以调用页面中的JS…

win10 + 独显 + Anaconda3 + tensorflow_gpu1.13 安装教程(跑bert模型)

这里面有很多坑&#xff0c;最大的坑是发现各方面都装好了结果报错 Loaded runtime CuDNN library: 7.3.1 but source was compiled with: 7.4.1&#xff0c;这是由于最新的tensorflow1.13需要用 Cudnn7.4.1编译。这个问题&#xff0c;StackOverflow上有人问到&#xff0c;但是…

Oracle client 安装、配置

一、安装 链接: https://pan.baidu.com/s/1Yph6hiNkCJsApAzu_Vx2ew 提取码: r9ye 二、配置 1、控制面板\所有控制面板项\管理工具\数据源(ODBC) 注&#xff1a;odbc 分 64 位和 32 位的2、测试 ODBC 连接 Oracle 数据库点击 ODBC&#xff0c;在“用户 DSN”页签下点击添加按钮…

ADO.NET- 基础总结及实例

1、ADO.NET基础介绍 &#xff08;1、程序要和数据库交互要通过ADO.NET进行&#xff0c;通过ADO.NET就能在程序中执行SQL了。ADO.Net中提供了对各种不同数据库的统一操作接口。 (2、直接在项目中内嵌mdf文件的方式使用SQL Server数据库&#xff08;基于服务的数据库&#xff09;…

Android发送短信字数问题

以前已经知道发送短信有70个字符的限制&#xff0c;但真到用的时候才发现还是不了解。中文英文各算几个字符&#xff1f;一开始按照老想法&#xff0c;GB码中文2个字节英文一个 字节来算&#xff0c;按70个汉字的限制可以发140个字节&#xff0c;但是发送的时候总是出错。后来在…

获取指定日期所属年份的第一天日期或最后一天日期

写了2个自定义函数&#xff0c;获取指定日期所在年份的第一天日期或最后一天的日期&#xff1a; SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- -- Author: Insus.NET -- Create date: 2019-05-09 -- Update date: 2019-05-09 -- Description: 获取指定日期所属年…

高效管理ASP.NET的JavaScript库

简介 对于ASP.NET开发人员来说,管理项目中的JavaScript都很随意&#xff1a; 我想这很大程度上可能是因为网上没有如何妥善处理ASP.NET中JavaScript的可靠信息。此文的目的就是提供一种最佳方案&#xff0c;用于管理ASP.NET中的JavaScript。该方案将能解决以下问题&#xff1a;…

【面试】c++单例模式

1. 单例模式 #include <iostream> using namespace std;class CSingleton { private:CSingleton() {} // 构造是私有的static CSingleton *m_pInstance; public:static CSingleton *GetInstance(){if (m_pInstance NULL) {m_pInstance n…

AIX HACMP集群切换测试实际案例解析

为验证AIX HACMP集群系统的稳定性及保障其上应用的连续性和可靠性&#xff0c;决定周五晚进行集群切换测试。下面是当次过程的文档总结和记录&#xff0c;方便以后参考并备案。系统环境&#xff1a;AIX 5.3数据库&#xff1a; DB2 V8.2存储&#xff1a; IBM DS4700,为两节点配置…

《Effective C++》阅后心得

《Effective C》阅后心得 这本书保存在我电脑里已经有两年之久了&#xff0c;记得以前模模糊糊翻过&#xff0c;大体上还有那么点点印象&#xff0c;最近花了一个星期仔仔细细的看了一篇&#xff0c;收获很大很大 首先对于很多C知识我都有那么个概念&#xff0c;真要我说出什么…

jvm_2

业务线程一直在等待&#xff0c;或者一直在运行&#xff0c;如果不是自己想要的状态&#xff0c;就表明有问题 死锁问题检测 上面程序之所以会死锁&#xff0c;因为下图所示&#xff0c;在-128~127范围内&#xff0c;Integer valueOf后对相同的int值会返回相同的对象&#xff0…

视频播放器

效果图 知识要点 surfaceView.getHolder().setFixedSize(176, 144);//设置分辨率 surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置surfaceview不维护自己的缓冲区&#xff0c;而是等待屏幕的渲染引擎将内容推送到用户面前 sur…

编了一个服务器

//服务器代码 / Sever.cpp : Defines the entry point for the console application. // #include <WinSock2.h> //包含Socket 2版本的头文件&#xff1b; #include <windows.h> #include <stdio.h> #pragma comment(lib, "WS2_32.lib")…

计算机学科技术前沿:互联网上信息可信性的现状

互联网的虚假信息很大一部分是由水军造成的。 研究报告显示&#xff0c;越来越常见的网络付费发贴行为虽然有益于商家&#xff0c;但却会影响到普通互联网用户的信息判断&#xff0c;使他们失去对网络信息的信任。 在中国&#xff0c;这些人被称作“网络水军”&#xff1a;一…

asp.net UpdatePanel的简单用法

局部更新是ajax技术的最基本&#xff0c;也是最重要的用法&#xff0c;今天大概把asp.net ajax中的局部更新控件 updatepanel的用法记录下&#xff0c;大家可以共同探讨 UpdatePanel控制页面的局部更新&#xff0c;这个更新功能依赖于scriptManger控件的EnablePartialRendering…

前端需要了解的http知识

http基本概念 http是一个无状态 &#xff0c;无连接的基于TCP协议的单向应用层协议 一、无连接 无连接即每次链接只处理一个请求&#xff0c;请求和应答后就断开链接 二、无状态 http的每次请求都是独立的&#xff0c;不相关的&#xff0c;协议对事物处理没有记忆功能。 HTTP无…

局域网中设备的管理之StackCluster

局域网中设备的管理通常采用 stack 、cluster和snmp等方法。 下面我们来讨论一下stack 和cluster。Stack 也叫作堆叠。堆叠是由一些通过堆叠口相连的以太网交换机组成的一个管理域&#xff0c;其中包括一个主交换机和若干个从交换机。堆叠在一起的以太网交换机可以看作为一个设…