3.2_5 内存映射文件

文章目录

  • 3.2_5 内存映射文件
    • (一)传统的文件访问方式
    • (二)内存映射文件(Memory-Mapped Files)
  • 总结

3.2_5 内存映射文件

image-20240316142622352

(一)传统的文件访问方式

image-20240316142913147

image-20240316143500573

  磁盘的存储是以块为单位的,如图,每一块的大小是1KB,那相应的,这个文件就会被拆分成若干个大小相等的块、每个块是1KB,刚好可以一一对应地放到磁盘里。

  如上图,有一个葵花宝典.txt文件,大小是3KB。

  这些块有可能被离散地放到磁盘的各个角落。

  如果一个进程想要访问这个文件的数据,应该怎么做呢?

  传统的方法是这样的:首先,每个进程拥有自己的虚拟地址空间,如果这个进程想要访问这个文件中的数据。它首先要使用open系统调用,来指明打开这个文件。接下来要使用seek系统调用,来指明它想要读取这个文件的哪一部分数据,操作系统会用一个读写指针来记录这个位置。接下来,进程可以使用read系统调用,来指明从当前读写指针的位置往后想要读入多少的数据。

  比如,此时该进程从磁盘读取了该文件的2部分数据,读入内存,就可以进行访问、修改。

  如果对这块数据进行了修改,进程想要保存这部分数据,那么还需要使用write系统调用,来把这部分数据给写回磁盘。


传统的文件访问方式:

  open系统调用——打开文件;

  seek系统调用——将读写指针移到某个位置;

  read系统调用——从读写指针所指位置读入若干数据(从磁盘读入内存);

  write系统调用——将内存中的指定数据写回磁盘(根据读写指针确定要写回什么位置)。

  在了解了传统的文件访问方式后,感觉很麻烦。那有没有什么方法可以让文件的访问变得更简单呢?——就有了内存映射文件。

(二)内存映射文件(Memory-Mapped Files)

  内存映射文件——操作系统向上层程序员提供的功能(系统调用)

  1.方便程序员访问文件数据;

  2.方便多个进程共享同一个文件。


  如果一个系统支持内存映射文件,那么一个程序员要访问一个文件,就会变得更简单。

内存映射文件的访问方式:

  open系统调用——打开文件;

  mmap系统调用——将文件映射到进程的虚拟地址空间。

  这个系统调用会给程序员返回一个指针,这个指针指向刚才映射的这片区域的起始地址。

image-20240316143811845

  接下来,就可以用访问内存的方式去访问这些文件数据了。

  什么意思呢?

  我们都写过C语言程序。如果给你一个起始地址、一个指针,那么你就可以用这个指针再加上地址偏移量,去访问这个起始地址后面的某些区域。

  所以,只要mmap系统调用,返回了这片区域的起始地址,那么就可以利用指针去访问到这个文件当中的任何一块数据。

  需要注意的是,使用mmap系统调用之后,只是建立了文件数据和内存之间的一个映射关系,但并没有把文件数据给直接读入内存。——这就相当于一个缺页的状态。

image-20240316144204827

  接下来的逻辑是这样的。假设此时想访问2部分的文件数据了。由于它只是一个映射关系,而真正的数据并没有调入内存,因此会引发一个缺页,操作系统这时会把磁盘中的文件数据调入内存。

  对于第3块数据也是同理,如果你想要访问它时,操作系统便会自动地把相应数据帮你调入到内存中。

  也就是说,作为程序员,我们不需要再调用read去读入数据了。读入数据的过程,是由操作系统自动帮我们完成的。

  那么,数据既然读入内存,我们的进程就可以对其进行访问、修改。比如我修改了第2块数据。

  最后,如果进程不再需要使用这个文件,那么系统可以使用close系统调用来关闭这个文件。当它关闭文件之后,操作系统会自动地把文件当中被修改的数据给写回磁盘。

image-20240316144539160

  可以看到,采用内存映射文件之后,程序员对文件数据的访问就方便多了。它只需要知道这个文件在内存当中的起始地址。接下来,按照访问内存的方式去访问这个文件当中的数据就可以了。至于文件数据的读入、写出,都是由操作系统自动来完成的。

  相比之下,传统文件访问方式,需要程序员自己去调用read、write系统调用,才可以读入、写出文件的数据。


内存映射文件的访问方式

  1.open系统调用——打开文件;

  2.mmap系统调用——将文件映射到进程的虚拟地址空间;

  3.close系统调用——关闭文件。

说明

  ①以访问内存的方式访问文件数据;

  ②文件数据的读入、写出由操作系统自动完成;

  ③进程关闭文件时,操作系统自动将文件被修改的数据写回磁盘。


  至此,我们已经理解了“内存映射文件”的第一个作用——方便程序员访问文件数据。

  接下来,我们再介绍它的第二个作用——方便多个进程共享同一个文件,是如何实现的。

  至此我们已经知道,对于一个文件葵花宝典.txt,它可以被进程1映射到自己的进程虚拟地址空间里。

  那么同样地,进程2也可以把这个文件映射到自己的虚拟地址空间里。

  此时,两个进程的虚拟地址空间是相互独立的,但是操作系统会把这两块虚拟地址空间映射到相同的物理内存上。

image-20240316145200169

  这不难实现,操作系统只需修改进程页表中对应的信息,将这些进程的页面映射到对应的页框上即可。——就能实现多个进程共享同一份文件数据。

image-20240316145334458

  在这种情况下,当一个进程修改了文件的数据之后,另一个进程立马也可以看到这块文件数据的改变。

  如图,进程1对第2块数据作了修改,那么会导致物理内存中的第2块数据的改变,从而也会导致进程2对第2块数据的访问结果发生改变。

  在物理内存中,一个文件对应同一份数据,当一个进程修改文件数据时,另一个进程可以立马“看到”。

总结

image-20240316145516068

  I/O效率的优化由操作系统负责,比如可以使用“预读入”、“缓写出”等策略。

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

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

相关文章

数据分析-Pandas如何观测数据的中心趋势度

数据分析-Pandas如何观测数据的中心趋势度 数据分析和处理中,难免会遇到各种数据,那么数据呈现怎样的规律呢?不管金融数据,风控数据,营销数据等等,莫不如此。如何通过图示展示数据的规律? 数据…

公众号留言功能恢复了,你的开通了吗?

了解公众号的人都知道,腾讯在2018年3月宣布暂停新注册公众号的留言功能,这之后注册的公众号都不具备留言功能。 这成了很多号主运营人的一块心病,也包括我。 没有留言,就好似一个人玩单机游戏,无法与读者互动&#xff…

柚见第十二期(随机匹配)

随机匹配 目的 为了帮大家更快地发现和自己兴趣相同的朋友 问题 匹配 1 个还是匹配多个? 答:匹配多个,并且按照匹配的相似度从高到低排序 怎么匹配?(根据什么匹配) 答:标签 tags 还可以根据 us…

经典机器学习模型(一)感知机模型

经典机器学习模型(一)感知机模型 感知机可以说是一个相当重要的机器学习基础模型,是神经网络和支持向量机的基础。 感知机是一个二分类的线性分类模型,之所以说是线性,是因为它的模型是线性形式的。 从《统计学习方法》中,我们…

【蓝桥杯】线段树

一.线段树 1.定义: 线段树是算法竞赛中常用的用来维护 区间信息 的数据结构。 线段树可以在O(logN) 的时间复杂度内实现单点修改、区间修改、区间查询(区间求和,求区间最大值,求区间最小值)等操作。 2.结构&#x…

【论文阅读】Improved Denoising Diffusion Probabilistic Models

Improved Denoising Diffusion Probabilistic Models 文章目录 Improved Denoising Diffusion Probabilistic Models概述Improving the Log-likelihoodLearning ∑ θ ( x t , t ) \sum_{\theta}(x_{t}, t) ∑θ​(xt​,t)Improving the Noise ScheduleReducing Gradient Nois…

基于Pnpm + Turborepo + QianKun的微前端+Monorepo实践

基于Pnpm Turborepo QianKun的微前端Monorepo实践 背景 微前端一般都会涉及多个代码库,很多时候要一个一个代码库地去开发维护和运行,很不方便,这种时候引入Monorepo搭配微前端就能很好地解决这种问题,一个代码库就可以完成整…

Spring Cloud Alibaba微服务从入门到进阶(三)(Spring Cloud Alibaba)

Spring Cloud Alibaba是spring Cloud的子项目 Spring Cloud Alibaba的主要组件(红框内是开源的) Spring Cloud是快速构建分布式系统的工具集, Spring Cloud提供了很多分布式功能 Spring Cloud常用子项目 项目整合 Spring Cloud Alibaba …

友塔游戏测试开发笔面经验

题目一 给定任意非负整数M,判断其能否表达为 M 2 ^a 2 ^b(a和b为非负整数),若可以输出a和b,若不能输出-1; 例如: 输入:6 输出: “1 2” 分析: void findAB(int M){} 为解决问题的主函数 …

优选算法[1]

目录 1.双指针; 2.滑动窗口; 3.二分查找; 4.前缀和; 1.双指针; 包括对撞指针和快慢指针(一般用来循环); 题目类型:移动零,复写零,快乐数,盛…

【每日力扣】235. 二叉搜索树的最近公共祖先与39. 组合总和问题描述

🔥 个人主页: 黑洞晓威 😀你不必等到非常厉害,才敢开始,你需要开始,才会变的非常厉害。 235. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义…

Python中类方法和静态方法的区别你知道吗?

​1.类方法 通过 classmethod 装饰器修饰的方法就是类方法 类方法可以通过类名或对象名调用,但是一般情况下使用类名调用(节省内存) 类方法中没有self.在类方法中不可以使用其它对象的属性和方法 类方法中一般会有一个参数cls,…