首页 > 系统相关 >操作系统知识强化内存映射文件(25王道)

操作系统知识强化内存映射文件(25王道)

时间:2024-09-17 22:23:12浏览次数:14  
标签:25 操作系统 映射 文件 内存 读入 数据

内存映射文件

本文根据25王道操作系统内存映射文件这一章所作跟课笔记

什么是内存映射文件

首先来看看什么是内存映射文件。简单来说,这是操作系统向上层的程序员提供的一个系统调用功能。通过这个功能,程序员可以很方便的去访问文件数据,另外这个功能也可以很方便的让多个进程共享同一个文件的数据。


先来解释第一点,为什么说内存映射文件可以让程序员更方便的去使用文件数据呢?那作为对比,我们先来看一下传统的文件访问方式。
来看一个例子,这是一个文件,名字叫葵花宝典.txt,这个文件要存放到磁盘里边。那磁盘的存储空间是以块为单位的,这样的一块大小是1 KB,那相应的这个文件就会被拆分成几个大小相等的块。每个块刚好是1 KB,刚好可以放到这个磁盘里边,那这些块有可能被离散的存放到磁盘的各个角落。


就像这个样子。那如果一个进程想要访问这个文件的数据,应该怎么做呢?
传统的做法是这样的,首先我们知道每个进程,它拥有自己的虚拟地址空间。那如果这个进程想要访问这个文件的数据,首先它需要使用open系统调用来指明,打开这个文件。接下来需要使用seek系统调用来指明它想要读取这个文件的哪部分数据。那操作系统会用一个读写指针来记录这个位置。


接下来进程可以使用read系统调用来指明从这个位置往后,它想要读入多少的数据?比如读入十个字节,或者读入20个字节等等。


那如果这一次进程要读入的这部分数据,刚好是存放在文件的第二个块这儿。那么,接下来操作系统就会把这一块的数据给读入内存。

image.png


现在这部分的数据被读入内存了,那进程就可以去访问内存里的这部分数据了。当然,进程也可以修改这一块的数据。最后如果想让刚才的修改被保存,那么这个进程它还需要使用write系统调用,把内存里的这一块数据写回磁盘。
所以这种传统的文件访问方式看起来很麻烦,那能不能让读写文件数据的这些操作变得更简单呢?

这就是内存映射文件要解决的问题。
来看一下,如果一个操作系统,它支持内存映射文件的功能,那么一个程序员或者说一个进程,它访问文件的方式就会变得更简单。
首先需要先使用open系统调用指明打开一个文件。接下来使用mmap这个系统调用,让操作系统把文件映射到进程的虚拟地址空间当中。

image.png


也就是这个样子。

image.png


那这个系统调用会给程序员返回一个指针。指向刚才映射的这片区域的起始地址。那接下来你就可以用访问内存的方式去访问这些文件数据了。什么意思呢?在c语言程序。,如果给你一个起始地址,某一个指针,那么你是不是可以用这个指针,再加上某一个地址的偏移量,去访问这个指针后面的某些区域对吧?
所以只要mmap这个系统调用给程序员返回了这片区域的起始地址。那接下来用这个指针就可以访问到这个文件的任何一个数据。
那你会发现在这个图里边,我们把文件的三个块涂成了灰色,原因是在使用mmap系统调用之后。操作系统只是建立了文件数据和内存之间的一个映射关系,但并没有把文件数据直接给读入内存。这就相当于一个缺页的状态。

假定,此时你要访问的数据刚好是在文件的第二块,在这个部分,

image.png


那此时操作系统发现这一块的数据还没有调入主存,也就是出现了一个缺页异常。此时操作系统会自动的把这一块的数据给读入主存。那同样的道理,如果你此时想要访问第三块数据,而第三块数据此时还处于缺页状态的话,那操作系统会自动的帮你把第三块数据读到内存里。

image.png


也就是说,我们作为程序员,我们不需要再自己去调用read函数,读入数据的过程是由操作系统自动的帮我们完成的。那这些数据被读入内存之后,那么进程就可以对它们为所欲为。比如说我可以修改第二块的数据。最后如果说这个进程它不再需要使用这个文件,那么进程可以使用close系统调用来关闭文件。
当它关闭文件之后,操作系统会自动的把文件当中被修改的数据给写回磁盘。那第二块数据是被修改过的,而第三块数据是没有被修改过的,所以操作系统会把第二块数据写回磁盘。


因此可以看到采用内存映射文件之后,程序员对文件数据的访问就方便多了。它只需要知道这个文件在内存当中的起始地址,接下来按照访问内存的方式去访问这个文件当中的数据就可以。那文件数据的读入或者写出都是由操作系统自动来完成的,相比之下,传统的文件访问方式需要程序员自己去调用read和write系统调用才可以读入文件的数据或者写出文件的数据。


实现文件的共享


那接下来我们再来解释内存映射文件的第二个作用,可以实现文件数据的共享。葵花宝典.txt这个文件,它可以被进程一用系统调用的方式映射到自己的虚拟地址空间里。


那同样的道理,另一个进程进程二也可以把这个文件映射到自己的虚拟地址空间里边,那此时两个进程的虚拟地址空间是相互独立的。但是操作系统会把这两块虚拟地址空间映射到相同的物理内存上。


操作系统只需要修改这两个进程的页表,让对应的页面映射到相同的一个物理页框上。那这么做,就可以让两个进程实际上是在共享同一份文件的数据。在这种情况下,当一个进程修改了文件的数据之后,另一个进程立马也可以看到这一块文件数据的改变。所以通过内存映射文件的方式多个进程,它们可以共享同一个文件的数据。
最后补充一点文件数据的读入和写出完全是由操作系统来负责的,就是什么时候要读入一个文件的数据块,什么时候要写出一个文件的数据块,这都是由操作系统来控制的。这么做的好处在于操作系统,它可以通过某些策略去优化磁盘IO的效率。比如说用预读入或者缓写出这样的策略,可以优化IO的效率。

若有收获,就点个赞吧

标签:25,操作系统,映射,文件,内存,读入,数据
From: https://blog.csdn.net/qq_56249308/article/details/142319877

相关文章

  • GYM 105125 C
    题目描述给定\(NM\)个数\(A_1,A_2,\dots,A_{NM}\),你要将这些数分成\(N\)个数组,每个数组\(M\)个数。接着你要将这些数组按字典序排序。对于排序后每个数组求出可能的字典序最小情况。思路我们从字典序的比较上来考虑,并把\(A\)排序。首先考虑当前数组\(i\)的第一位......
  • 【25.2】C++智能交友系统
    Girl类代码补充对一些成员函数定义的修改.h文件#pragmaonce#include<string>#include<sstream>usingnamespacestd;classBoy;classGirl{public: Girl(); Girl(intage,stringname,intstyle); ~Girl(); intgetAge()const; stringgetName()const......
  • 进程的内存分配
    在操作系统中,进程的内存分配是指操作系统为每个进程管理和分配所需的内存资源。内存管理是操作系统的核心功能之一,它涉及到为进程提供虚拟内存、物理内存分配、页表管理、以及地址转换等操作。操作系统通过虚拟内存机制,使每个进程都可以认为自己拥有独立的、连续的内存空间。1.......
  • 【计算机毕设选题】2025计算机毕业设计选题,毕设100个热门选题推荐
    毕业设计作为计算机专业学生学习阶段的压轴之作,不仅是展示知识与技能的机会,更是对实际开发能力的全面考验。选题是整个毕业设计过程中至关重要的一环,一个合适且有挑战性的题目能大大提升毕业设计的质量。然而,很多学生在选题时面临着两个难题:一是题目过于常规,无法充分展现个......
  • 深入剖析:C++类对象的内存布局与优化
    深入剖析:C++类对象的内存布局与优化引言在C++编程中,理解类对象的内存布局对于优化内存使用和提高程序性能至关重要。本文将详细介绍C++类对象的内存布局,包括数据成员、虚函数表指针以及静态变量和静态方法在内存中的位置。通过这些知识,我们可以更好地设计和优化我们的类结......
  • 前端JavaScript面试重难点: 闭包+内存泄漏+垃圾回收机制
    前置知识!!!闭包是Javascript语言的一个重难点,也是它的特色,很多高级应用都要依靠闭包来实现。在各种专业文献上学习"闭包"的时候,就一个感觉–“抽象”!特别是学习内存泄漏的时候,没想明白为什么使用闭包的时候不及时清除函数中的元素会导致内存泄漏,直到我的......
  • JVM 内存
    目录堆栈默认垃圾回收策略垃圾回收参数G1垃圾回收查看内存的命令堆栈堆:存储对象和数组,堆大小动态分配(-Xms、-Xmx),线程共享,垃圾回收栈:存储局部变量、方法参数、方法栈,相对较小(-Xss),方法完成时释放,线程私有堆栈大小配置-Xmx:设置JVM最大可用内存,默认系统内存的1/4,最大......
  • 支持外部内存功能的STL容器使用方法分享
    一、分享简介    C++的STL支持了多种容器供开发者操作,然而这些容器使用的是系统内存,使用者无法直接管理。边缘端的嵌入式设备通常会要求对使用的内存进行管理,因此封装出支持外部内存功能的STL容器就显得十分必要。本案例针对被封装容器的使用方法进行了经验分享,具体涉及3......
  • C++内存管理详解:各类变量的存储区域
      在C++中,变量的存储位置取决于它们的类型和生命周期。那么不同的各个变量究竟存储在哪个区域呢?1.不同类型的变量我们首先从变量类型的不同来说明:1.全局变量和静态变量 -存储区:全局/静态区(静态区)-说明:全局变量(包括文件级和函数级的)和使用`static`关键字声明的变......
  • JVM内存结构
    JVM内存结构JVM在执行程序的过程中会将内存划分为五个不同的数据区域:虚拟机栈、本地方法栈、方法区、堆、程序计数器。JVM五个区中虚拟机栈、本地方法栈、程序计数器为线程私有,方法区和堆为线程共享区。JVM不同区域的占用内存大小不同,一般情况下堆最大,用来存放”对象“,程......