内存映射的原理

由于所有用户进程总的虚拟地址空间比可用的物理内存大很多,因此只有最常用的部分才与物理页帧关联。这不是问题,因为大多数程序只占用实际可用内存的一小部分。

在将磁盘上的数据映射到进程的虚拟地址空间的时,内核必须提供数据结构,以建立虚拟地址空间的区域和相关数据所在位置之间的关联。例如,在映射文本文件时,映射的虚拟内存区必须关联到文件系统的硬盘上存储文件内容的区域。如图所示:

当然,给出的是简化的图,因为文件数据在硬盘上的存储通常并不是连续的,而是分布到若干小的区域。内核利用address_space数据结构,提供一组方法从后备存储器读取数据。例如,从文件系统读取。因此address_space形成了一个辅助层,将映射的数据表示为连续的线性区域,提供给内存管理子系统。

按需分配和填充页称为按需调页法。它基于处理器和内核之间的交互,使用的各种数据结构如图所示:

过程如下:

CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步(如下图):

首先,将给定一个逻辑地址(其实是段内偏移量,这个一定要理解!!!),CPU要利用其段式内存管理单元,先将为个逻辑地址转换成一个线程地址,

其次,再利用其页式内存管理单元,转换为最终物理地址。

     

 这样做两次转换,的确是非常麻烦而且没有必要的,因为直接可以把线性地址抽像给进程。之所以这样冗余,Intel完全是为了兼容而已。

  • 进程试图访问用户地址空间中的一个内存地址,利用上面的线性地址去查找页表,确定对应的物理地址,但使用的页表无法确定物理地址(物理内存中没有关联页)
  • 处理器接下来触发一个缺页异常,发送到内核。
  • 内核会检查负责缺页区域的进程地址空间数据结构,找到适当的后备存储器,或者确认该访问实际上是不正确的(未映射,未使用)
  • 分配物理内存页,并从后备存储器读取所需数据填充。
  • 借助于页表将物理内存页并入到用户进程的地址空间,应用程序恢复执行。

这些操作对用户进程是透明的。换句话说,进程不会注意到页是实际在物理内存中,还是需要通过按需调页加载。

 

在整个过程中可能需要解决以下几个问题:

1)系统如何感知进程当前所需页面不在主存(页表机制);
2)当发现缺页时,如何把所缺页面调入主存(缺页中断机构);
3)在置换页面时,根据什么策略选择欲淘汰的页面(置换算法)。

页表机制

 

状态位(中断位):标识该页是否在内存(0或1);
访问位:标识该页面的近来的访问次数或时间(换出);
修改位:标识此页是否在内存中被修改过;
外存地址:记录该页面在外存上的地址,即(外存而非内存的)物理块号。

缺页中断机制

程序在执行时,首先检查页表,当状态位指示该页不在主存时,则引起一个缺页中断发生,其中断执行过程与一般中断相同:
保护现场(CPU环境);
中断处理(中断处理程序装入页面);
恢复现场,返回断点继续执行。

置换算法

FIFO

LRU

LFU

 

时间: 2024-09-19 23:05:55

内存映射的原理的相关文章

java 深入理解内存映射文件原理_Android

内存映射文件原理 首先说说这篇文章要解决什么问题? 1.虚拟内存与内存映射文件的区别与联系. 2.内存映射文件的原理. 3.内存映射文件的效率. 4.传统IO和内存映射效率对比. 虚拟内存与内存映射文件的区别与联系 二者的联系 虚拟内存和内存映射文件都是将一部分内容加载到,另一部分放在磁盘上的一种机制,二者都是应用程序动态性的基础,由于二者的虚拟性,对于用户都是透明的. 虚拟内存其实就是硬盘的一部分,是计算机RAM与硬盘的数据交换区,因为实际的物理内存可能远小于进程的地址空间,这就需要把内存中暂

内存映射文件原理及实例

本课中我们将要讲解内存映射文件并且演示如何运用它.您将会发现使用内存映射文件是非常简单的. 理论:如果您仔细地研究了前一课的例子, 就会发现它有一个严重的缺陷:如果您想读的内容大于系统分配的内存块怎么办?如果您想搜索的字符串刚好超过内存块的边界又该如何处理?对于第一个问题,您也许会说,只要不断地读就不解决了吗.至于第二个问题,您又会说在内存块的边界处做一些特别的处理,譬如放上一些标志位就可以了.原理上确实是行得通,但是这随问题复杂程度加深而显得非常难以处理.其中的第二个问题是有名的边界判断问题,

汇编教程之内存映射文件

本课中我们将要讲解内存映射文件并且演示如何运用它.您将会发现使用内存映射文件是非常简单的. 理论: 如果您仔细地研究了前一课的例子, 就会发现它有一个严重的缺陷:如果您想读的内容大于系统分配的内存块怎么办?如果您想搜索的字符串刚好超过内存块的边界又该如何处理?对于第一个问题,您也许会说,只要不断地读就不解决了吗.至于第二个问题,您又会说在内存块的边界处做一些特别的处理,譬如放上一些标志位就可以了.原理上确实是行得通,但是这随问题复杂程度加深而显得非常难以处理.其中的第二个问题是有名的边界判断问题

mongodb mmap内存映射是把文件中数据全部映射到内存中的吗?

问题描述 mongodb mmap内存映射是把文件中数据全部映射到内存中的吗? 资料上说:在Mongodb中,其使用了操作系统底层提供的内存映射机制,即MMAP.MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的信息位置就会在内存中有对应的地址空间,这时对文件的读写可以直接用指针来做,而不需要read/write函数了.同时操作系统会将数据刷新保存到磁盘上. 我有个疑问:这个内存映射,是把文件中数据全部映射到内存中的吗?还是只是映射一部分内容,那么这部门内容又是什么的呢? 请专

内存映射文件

1.简介 内存映射文件,机器学习读大文件时可用,效率比传统IO要高. 用于内存映射文件的这部分内存,在Java的堆空间以外. 常见nio相关类见< java NIO>,http://blog.csdn.net/chuchus/article/details/51886586  . 1.1 传统读写 在传统的文件IO中,底层是类似C语言的read().write()操作 ,操作系统  由当前的[用户态]切换到[内核态],然后读数据至[OS缓冲区],再拷贝到[进程的私有地址空间]中去,这样便完成了

我用了共享内存映射,但是,串口来的数写到共享内存里,就是更新不到磁盘文件里去咋办??

问题描述 我用了共享内存映射,但是,串口来的数写到共享内存里,就是更新不到磁盘文件里去咋办?? 共享内存映射,flushviewoffile,更新磁盘文件(那个flushviewoffile 返回都是对的可是文件里就是没有东西) 解决方案 先看i数据是否正确接收了,有没有写入共享内存.

c++-求教!通过内存映射,实现生成的数组存储到文件中,显示出来头100个数?

问题描述 求教!通过内存映射,实现生成的数组存储到文件中,显示出来头100个数? 我目前就了解个大概,现在我不明白const DWORD mmf_size = 512*1024;//?这个地方不懂 ,这个原来的代码部分,我拿别人的代码改的,增加了自己的double的动态数组SigNRead,这个怎么弄 我就想实现,通过内存映射 实现写入 读取 double数组 数组有 1列 90000行个double数组成. #include #include #include #include #define

建立对象数据库-内存映射范式,需要中间层容器的支持

对象|数据|数据库|中间层 在<设想使用XML和关系数据库形成一个对象数据库>一文中,已经阐述了关系数据库和对象数据库的主要区别:对外键的使用是通过直接记录,还是遍历外键子表来获得.而这里,是面对另一个重要的区别:如何释放对象的资源.对于对象数据库而言,它等同于是一批直接存于数据库中的串行化对象,它的实际存储形式到底是不是按关系结构存储并不是最重要的,重要的是调用程序读入内存的就是一个对象,而不是游标映射:这样,使用对象数据库就必须存在着一个如何清除用完的对象资源的问题:同时由于对象数据库必然

内存映射修改大文件

本文介绍利用内存映射文件修改大文件:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤: 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件: 创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件: 让系统将文件映射对象的全部或一部分映射到你的进程地址空间中: 当完成对内存映射文件的使用时,必须执行下面这些步骤将它清除: 告诉系统从你的进程的地址空间中撤消文件映射内核对象的映像: 关闭文件映射内核对象: 关闭文件内核对象: 下面将用一个