mmap 和 read 系统流程

在linux文件系统中,通常使用open(), read()读取文件,但操作系统同样提供了mmap()作为读取文件的方式,而这两者有什么不同呢?什么时候用read(), 什么时候用mmap()?

首先,read 的通常使用方法是 read(fd, buffer, size),将要读取的数据读到buffer中。这就涉及到两个步骤,read是系统调用函数,每次使用read都要进入内核态,进行上下文切换。内核首先将文件数据从磁盘读入page cache缓存,再将数据从page cache拷贝到buffer中。上下文切换和拷贝要消耗一定性能。

而如果使用 mmap 命令,VFS(虚拟文件系统)会分配对应的虚拟内存空间,记录目标文件的 inode 和其他属性,将起始虚拟地址返回给进程。当进程想要访问某部分数据时,需要进行地址翻译,但此时没有更新页表,会触发缺页中断。linux根据VMA中记录的 inode 信息,调用对应的文件系统进行处理。文件系统读取该页,返回给VFS,VFS再更新页表,返回对应的物理页。

在 mmap 之后,后续的读写操作都是在内存中进行,不需要再读磁盘和进入内核态。

mmap的优点

因此 mmap 比起 read ,有如下优势:

  1. 对于随机访问,不用频繁 lseek。因为 mmap 是将整个文件映射到虚拟空间,在读取时再按需分配物理内存。
  2. 减少后续系统调用次数。后续读文件时不需要再进入内核态,减少了上下文切换
  3. 减少数据拷贝。免去了page cache 到 buffer 的数据拷贝。
  4. 当多个进程将同一页面映射到内存时,数据可以在这些进程之间共享。对于 只读 的页面可以完全共享,需要写入的文件可以使用COW(copy on write)私有化。这样节省了大量内存。

mmap also allows the operating system to optimize paging operations. For example, consider two programs; program A which reads in a 1MB file into a buffer creating with malloc, and program B which mmaps the 1MB file into memory. If the operating system has to swap part of A's memory out, it must write the contents of the buffer to swap before it can reuse the memory. In B's case any unmodified mmap'd pages can be reused immediately because the OS knows how to restore them from the existing file they were mmap'd from. (The OS can detect which pages are unmodified by initially marking writable mmap'd pages as read only and catching seg faults, similar to Copy on Write strategy).

mmap 还可以优化操作系统分页。对于进程A、B,如果A通过 read 读取了1MB数据到buffer中,而B通过 mmap 读取1MB数据。如果OS想要把A中的 buffer 换入磁盘,首先要将buffer中的内容写入磁盘,才可以重用该物理页。而对于B中没有被修改过的 mmap 页,OS可以直接重用,因为OS可以从文件中再重新读取该页来恢复数据。

那么,如果 mmap 比起 open(),read() 有这么多优点,为什么不用 mmap 呢?对于系统来说,有优点往往意味着存在对应的缺点,这才是系统设计中的trade off。

mmap的缺点

  1. mmap 每次以页为单位从文件中读取数据,因此映射的页面大小始终是整数。对于小文件可能会造成较多的内部碎片。同时,在读取数据时也需要显式修正数据在页面中的偏移量。
  2. mmap 需要连续的虚拟内存空间用于储存文件,如果文件较大,对于32位地址空间的系统来说,可能找不到足够大的连续区域。
  3. mmap 本身开销比 read 大,因为mmap涉及更多的系统调用,需要触发缺页中断,更改虚拟内存映射。

总结

由于read 读取文件更加直观和易于理解,因此初学者依然使用 read 较多。但如果需要随机访问数据,或者和其他进程共享数据,用 mmap 不失为一个更好的选择。

什么时候选择mmap而非read?的更多相关文章

  1. Web前端开发:为何选择MVVM而非MVC

    在Web中充斥着所谓的MVC框架,而在我看来,因为一些关键性的技术原因,MVC在Web前端开发中根本无法使用(对的,是无法,而不是不该) 在Web中充斥着所谓的MVC框架,而在我看来,因为一些关键性的 ...

  2. 【转】Web前端开发:为何选择MVVM而非MVC

    在Web中充斥着所谓的MVC框架,而在我看来,因为一些关键性的技术原因,MVC在Web前端开发中根本无法使用(对的,是无法,而不是不该) 在Web中充斥着所谓的MVC框架,而在我看来,因为一些关键性的 ...

  3. jQuery获取Select选择的Text(非表单元素)和 Value(表单元素)(转)

    jQuery获取Select选择的Text和Value: 语法解释: . $("#select_id").change(function(){//code...}); //为Sel ...

  4. 页面中的radio选择适合的非空判断

     var cyjb=$('input:radio[name="jcrwModel.cyjb"]:checked').val();                if(cyjb==n ...

  5. (转)PHP线程安全与非线程安全的区别:如何选择用哪一个?

    PHP线程安全与非线程安全的区别:如何选择用哪一个? 很多时候,我们在做PHP环境配置的时候,很多人都是直接去乱下载PHP版本的,但是他不清楚:从2000年10月20日发布的第一个Windows版的P ...

  6. mmap映射区和shm共享内存的区别总结

    [转载]原文链接:https://blog.csdn.net/hj605635529/article/details/73163513 linux中的两种共享内存.一种是我们的IPC通信System ...

  7. Html5 简单选择排序演示

    简单选择排序,是选择排序算法的一种.基本思想:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止.由于在每次循环中,会对数值相等的元素改变位置,所以属于非稳定 ...

  8. Jquery 系列(2) 选择元素

    Jquery基础学习 jQuery利用css选择符的能力,能够在DOM中快捷而轻松地获取元素. 主要内容如下: 介绍DOM树 如何通过CSS选择符在页中查找元素 扩展jQuery标准的CSS选择符 选 ...

  9. ORACLE RAC 下非缺省端口监听配置(listener.ora tnsnames.ora)

    不论是单实例还是RAC,对于非缺省端口下(1521)的监听器,pmon进程不会将service/instance注册到监听器,即不会实现动态注册.与单实例相同,RAC非缺省端口的监听器也是通过设置参数 ...

随机推荐

  1. 关于Java中for,while,if,方法的练习

    练习 计算0到100之间的奇数和偶数和 package com.kangkang.forDemo;​public class demo01 {    public static void main(S ...

  2. 后端程序员之路 13、使用KNN进行数字识别

    尝试一些用KNN来做数字识别,测试数据来自:MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burgesh ...

  3. ElasticSearch 数据建模

    公号:码农充电站pro 主页:https://codeshellme.github.io 通常在使用 ES 构建数据模型时,需要考虑以下几点: 字段类型 是否需要搜索与分词 是否需要聚合与排序 是否需 ...

  4. ElasticSearch 集群的规划部署与运维

    公号:码农充电站pro 主页:https://codeshellme.github.io 1,常见的集群部署方式 ES 有以下不同类型的节点: Master(eligible)节点:只有 Master ...

  5. selenium之元素定位的方法(二)

    XPath定位是XML Path的缩写,称为XML路径语言,是在XML文档中查找信息的一种语言,可用来再XML文档中对元素和属性进行搜索.XPath使用路径表达式来选取XML文档中的节点或节点集. X ...

  6. ajax请求添加自定义header参数

    beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("X-Auth0-Token", g ...

  7. springboot源码解析-管中窥豹系列之BeanFactoryPostProcessor(十一)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  8. LZZ高级程序语言设计之多重for循环

    public class Mq { public static void main(String args[]) { System.out.println("到底去还是不去呢?") ...

  9. 2019 GDUT Rating Contest II : Problem F. Teleportation

    题面: Problem F. Teleportation Input file: standard input Output file: standard output Time limit: 15 se ...

  10. (3)MySQL进阶篇SQL优化(索引)

    1.索引问题 索引是数据库优化中最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数 的SQL性能问题.本章节将对MySQL中的索引的分类.存储.使用方法做详细的介绍. 2.索引的存储分类 ...