参考文献:

《从内核文件系统看文件读写过程》http://www.cnblogs.com/huxiao-tee/p/4660352.html?utm_source=tuicool&utm_medium=referral

《mmap是什么》http://www.cnblogs.com/huxiao-tee/p/4660352.html?utm_source=tuicool&utm_medium=referral

正文:

首先说一下文件系统,Linux文件系统的三层结构想必大家多少都了解一些,每个进程中都有一个用户文件描述符表,表项指向一个全局的文件表中的某个表项,文件表表项有一个指向内存inode的指针,每个inode唯一标识一个文件。如果同时有多个进程打开同一文件,他们的用户文件描述符表项指向不同的文件表项,但是这些文件表项会指向同一个inode。

此时又会引出另外一个东东:page cache。内核会为每个文件单独维护一个page cache,用户进程对于文件的大多数读写操作会直接作用到page cache上,内核会选择在适当的时候将page cache中的内容写到磁盘上(当然我们可以手工fsync控制回写),这样可以大大减少磁盘的访问次数,从而提高性能。Page cache是linux内核文件访问过程中很重要的数据结构,page cache中会保存用户进程访问过得该文件的内容,这些内容以页为单位保存在内存中,当用户需要访问文件中的某个偏移量上的数据时,内核会以偏移量为索引,找到相应的内存页,如果该页没有读入内存,则需要访问磁盘读取数据。为了提高页得查询速度同时节省page cache数据结构占用的内存,linux内核使用树来保存page cache中的页。

在了解了以上的基础之后,我们就来比较一下mmap和read/write的区别,先说一下read/write系统调用,read/write系统调用会有以下的操作:

  1. 访问文件,这涉及到用户态到内核态的转换
  2. 读取硬盘文件中的对应数据,内核会采用预读的方式,比如我们需要访问100字节,内核实际会将按照4KB(内存页的大小)存储在page cache中
  3. 将read中需要的数据,从page cache中拷贝到用户缓冲区中

整个过程还是比较艰辛的,基本上涉及到用户内核态的切换,还有就是数据拷贝接下来继续说mmap吧,mmap系统调用是将硬盘文件映射到用内存中,说的底层一些是将page cache中的页直接映射到用户进程地址空间中,从而进程可以直接访问自身地址空间的虚拟地址来访问page cache中的页,这样不会涉及page cache到用户缓冲区之间的拷贝,mmap系统调用与read/write调用的区别在于:

  1. mmap只需要一次系统调用,后续操作不需要系统调用
  2. 访问的数据不需要在page cache和用户缓冲区之间拷贝

从上所述,当频繁对一个文件进行读取操作时,mmap会比read高效一些。

最后再说一下page cache的话题,从上面所说我们从磁盘文件中读取的内容都会存在page cache中,但当我们关闭这个文件时,page cache中内容会立马释放掉吗?答案是否,磁盘的读取速度比内存慢太多,如果能命中page cache可以显著提升性能,万一后续又有对这个文件的操作,系统就可以很快速的响应。当然,这些文件内容也不是一直存在page cache中的,一般只要系统有空闲物理内存,内核都会拿来当缓存使用,但当物理内存不够用,内存会清理出部分page cache应急,这也就是告诉我们程序对于物理内存的使用能省则省,交给内核使用,作用很大。

还有就是普通的write调用只是将数据写到page cache中,并将其标记为dirty就返回了,磁盘I/O通常不会立即执行,这样做的好处是减少磁盘的回写次数,提供吞吐率,不足就是机器一旦意外挂掉,page cache中的数据就会丢失。一般安全性比较高的程序会在每次write之后,调用fsync立即将page cache中的内容回写到磁盘中。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

mmap为什么比read快相关推荐

  1. 【linux】为什么 mmap 比系统调用快

    1.概述 翻译:Why mmap is faster than system calls 当我问我的同事为什么 mmap 比系统调用更快时,答案不可避免地是"系统调用开销":跨越用 ...

  2. C++“读取“大量数据时--快读

    在一些算法题目中中,有的程序会被卡常数,就是说,程序虽然时间复杂度可以接受,但因为算法本身的时间常数过大,导致程序在一些算法竞赛中超时.这是,快读就显得尤为重要了. 当然,如果程序算法本身就不高效,快 ...

  3. 重新认识 Java 中的内存映射(mmap)

    mmap 基础概念 mmap 是一种内存映射文件的方法,即将一个文件映射到进程的地址空间,实现文件磁盘地址和一段进程虚拟地址的映射.实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而 ...

  4. linux系统提升硬盘写速度的方法

    LINUX系统写速度问题解决过程 问题描述: linux系统下写速度只有2GB/s左右,无法支持2.5G采样率连续采集,达不到预期的性能.而同样的代码在windows系统下,却可以支持2.5G采样率连 ...

  5. RocketMQ4.X消息队列详细笔记

    人不能没有批评和自我批评 那样一个人就不能进步. 目录 JMS和消息中间件介绍 JMS消息服务和使用场景 消息中间件常见概念和编程模型 主流消息队列和技术选型讲解 基础介绍和阿里云服务器快速部署 Ro ...

  6. RocketMQ学习笔记(二)

    第六章 RocketMQ生产者核心配置和核心知识讲解 第1集 消息队列RocketMQ4.X生产者核心配置讲解 简介:消息队列RocketMQ4.X核心配置讲解 生产者常见核心配置 compressM ...

  7. 抖音品质建设 - iOS启动优化《实战篇》

    前言 启动是 App 给用户的第一印象,启动越慢,用户流失的概率就越高,良好的启动速度是用户体验不可缺少的一环.启动优化涉及到的知识点非常多,面也很广,一篇文章难以包含全部,所以拆分成两部分:原理和实 ...

  8. RocketMQ源码级别面试题板块

    目录 事务消息篇 消费者端 Broker端 面试题版块 Kafka版块 Kafka生产消息为什么快之PageCache kafka的生产者和消费者如何借助Pagecache实现快速读和快速写 Kafk ...

  9. rocketMQ-消息队列

    RocketMQ4.X基础介绍 官网地址 http://rocketmq.apache.org/ 参考资料 http://jm.taobao.org/2017/01/12/rocketmq-quick ...

  10. 讲一讲什么是 MMAP

    1. mmap 基础概念 mmap 即 memory map,也就是内存映射. mmap 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一 ...

最新文章

  1. R语言绘制堆叠的环状条形图
  2. 新手java五子棋完整代码判断落子落在线上_Java初学者,编写小游戏五子棋的问题?...
  3. DFS与BFS的总结
  4. 怎么查看电脑配置参数linux,linux下查看电脑配置
  5. [Swift]LeetCode45. 跳跃游戏 II | Jump Game II
  6. 原生JS forEach()和map()遍历的区别以及兼容写法
  7. Google DeepMind围棋程序AlphaGo的分析
  8. Scala集合常用方法:reduceLeft/reduceRight
  9. linux删除目录是显示非空,Linux删除非空目录
  10. delphi基本语法
  11. Codeforces Round #280 (Div. 2)
  12. oracle导出dmp空表导不出来,如何解决Oracle11g使用dmp命令无法导出空表问题
  13. 4g模块注册上网 移远_物联网模组龙头移远通信
  14. matlab信息量估计法估计嵌入率,LSB密写分析-信息量估计法
  15. 【Matlab】建立最优控制LQR控制器模型
  16. html嵌入word文档,网页中嵌入word文档和导出数据到word文档
  17. 袖珍磁带的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  18. (专升本)PowerPoint(设置幻灯片的动画效果)
  19. Amazon,我们完全不能接受 — 因此我们必须变更 Elastic 许可协议
  20. BZOJ 2144 跳跳棋

热门文章

  1. ICSharpCode.SharpZipLib实现压缩解压缩
  2. gbdt 算法比随机森林容易_数据挖掘面试准备(1)|常见算法(logistic回归,随机森林,GBDT和xgboost)...
  3. Hadoop 开源调度系统zeus
  4. jqgrid 点击列头的超链接或按钮时,不触发列排序事件
  5. 《R数据可视化手册》——2.5 绘制箱线图
  6. C# string byte[] Base64 常用互相转换
  7. jdbc 连接oracle 数据库格式
  8. 迁移 Linux 系统,第 1 部分——如何迁移备份和裸机恢复 Linux 系统
  9. mysql慢查询优化
  10. 搞定机器学习面试,这些是基础!