一、问题背景

Linux下,针对文件读写操作,一般有三个步骤:
1)把文件内容读入到内存中;调用read(系统调用),从内核态读取文件内容到虚拟内存;
2)修改内存中的内容;在用户空间修改内存中的信息;
3)把内存的数据写入到文件中;调用write(系统调用),从用户态将修改后的内容写入到文件;
过程如下图所示:(本文只讨论mmap,关于page cache,请查看:https://www.cnblogs.com/ronnieyuan/p/12377059.html)

显然一次文件的修改操作,我们对文件内容拷贝了两次;

如何优化上述的文件读写操作?如果可以直接在用户空间读写page cache,那么就不需要将文件数据拷贝到用户空间缓存区这个动作了,mmap即可完成;

使用mmap系统调用可以将用户空间的虚拟内存地址与文件进行映射绑定,对映射或的虚拟内存地址进行读写操作,就如同对文件进行读写操作一样。原理图如下所示:

通过上图可以看出,读写文件都需要经过页缓存,所以mmap映射的正是文件的页缓存,而非磁盘中的文件本身。由于mmap映射的是文件的页缓存,所以就涉及到同步的问题,即页缓存会在什么时候把数据同步到磁盘。Linux内核并不会主动把mmap映射的页缓存同步到磁盘,而是需要用户主动触发。同步mmap映射的内存到磁盘有4个时机:1)调用 msync 函数主动进行数据同步(主动);2)调用 munmap 函数对文件进行解除映射关系时(主动);3)进程退出时(被动);4)系统关机时(被动)。备注:下面示例实测不调用munmap也会写回到文件,保险起见还是主动同步数据到文件,详细的还未研究。

二、mmap示例

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>int main(void)
{int fd;fd = open("in.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);if (-1 == fd){return -1;}void *result;result = mmap(0, 1024, \PROT_READ|PROT_WRITE, \MAP_SHARED, \fd, 0);if (result == (void *)-1) {printf("mmap failed: %s\n", strerror(errno));return -1;}close(fd);//映射完可以立即关闭fd,不应该映射及修改strncpy(result, "z", 1);munmap(0, 1024);return 0;
}

三、理论理解

彻底理解mmap()

Page Cache(页缓存)

mmap 内存映射详解

Linux mmap完全剖析​​​​​​​

Linux编程之mmap示例相关推荐

  1. 【Linux】Linux编程之 mmap解析

    前言 虚拟内存系统通过将虚拟内存分割为称作虚拟页(Virtual Page,VP)大小固定的块,一般情况下,每个虚拟页的大小默认是4096字节.同样的,物理内存也被分割为物理页(Physical Pa ...

  2. linux编程之pthread_create函数

    linux编程之pthread_create函数UNIX环境创建线程函数, 具体格式: #include<pthread.h> int pthread_create(pthread_t * ...

  3. linux c 多显卡编程,Linux 编程之GPU计算(转)

    08月11日(星期六) Linux 编程之GPU计算(转) 关于brookgpu的简要介绍看下面的链接: 本文翻译了斯坦福大学网站上的关于brookgpu语言的一篇文章,原文在: 关于brookgpu ...

  4. Linux编程之GCC编译工具实战-夏曹俊-专题视频课程

    Linux编程之GCC编译工具实战-6075人已学习 课程介绍         本课程使得学员能够学会在linux中如何编译C/C++程序,使用GCC工具如何编译静态库,动态库,如何配置运行动态库. ...

  5. Linux编程之epoll

    前言 I/O多路复用有很多种实现.在linux上,2.4内核前主要是select和poll,自Linux 2.6内核正式引入epoll以来,epoll已经成为了目前实现高性能网络服务器的必备技术.尽管 ...

  6. Linux编程之ioctl

    在和设备驱动程序通信时,ioctl是很常用的一个调用,常用来配置.查询或者修改设备的配置.反过来说,编写驱动程序时,ioctl也是经常要实现的一个接口,以便应用程序可以方便地控制设备驱动. 应用程序中 ...

  7. linux编程之mprotect

    mprotect: 设置内存访问权限 mmap 的第三个参数指定对内存区域的保护,由标记读.写.执行权限的 PROT_READ.PROT_WRITE 和 PROT_EXEC 按位与操作获得,或者是限制 ...

  8. linux编程之GDB调试

    GDB是一套字符界面的程序集,可以用它在linux上调试C和C++程序,它提供了以下的功能: 1 在程序中设置断点,当程序运行到断点处暂停 2 显示变量的值,可以打印或者监视某个变量,将某个变量的值显 ...

  9. linux编程之pipe()函数

    管道是一种把两个进程之间的标准输入和标准输出连接起来的机制,从而提供一种让多个进程间通信的方法,当进程创建管道时,每次 都需要提供两个文件描述符来操作管道.其中一个对管道进行写操作,另一个对管道进行读 ...

最新文章

  1. 从现在到未来50年,传感器将如何改变世界?
  2. java网络编程之TCP通讯
  3. android 打卡app,日常小打卡app
  4. 【新星计划】Linux命令行相关指令汇总
  5. java datainputstream_Java DataInputStream readUnsignedByte()方法
  6. iOS开发日记4-第三方登录(ShareSDK)
  7. 【TensorFlow-windows】keras接口——卷积核可视化
  8. 监控mysql锁定状态_企业实战Mysql不停机维护主从同步
  9. GAN全套学习笔记/论文
  10. 【HDU1166】敌兵布阵,线段树练习
  11. (转)Fabric 1.0 读写集
  12. OFFICE技术讲座:双层字体引擎的提出
  13. 怎样做小游戏挖金子(VC,源码4)
  14. HTML与CSS案例——人物简介
  15. 离线语音合成使用——科大讯飞or云知音or百度语音
  16. 新知实验室 TUIKaraoke在线 K 歌
  17. 中柏平板bios对照表_BIOS详解及中英文对照表
  18. [CS144] Lab 1: stitching substrings into a byte
  19. 《“边缘计算+”技术白皮书》发布!
  20. 初步了解指针------指针的基本概念

热门文章

  1. 日常健身养生八大法宝
  2. brackets编写java,Brackets - 一款免费的前端开发工具
  3. nginx 修改fcgi配置Unix socket
  4. ubuntu beep 蜂鸣
  5. 马宁的Windows Mobile开发培训概述
  6. 网络编程之UDP通信
  7. 放大镜 讲课_《 放 大 镜 》教 学 设 计
  8. java程序员年终总结工作总结
  9. 高端婚礼的布置技巧 8个细节不能忽略
  10. Zbar识别QRcode解读