专栏首页飞天小牛肉内存管理两部曲之虚拟内存管理

内存管理两部曲之虚拟内存管理

传统存储管理存在的问题

虚拟内存这个东西他为什么会出现?他出现的背景是什么?

前文 内存管理两部曲之物理内存管理 提到:随着用户程序功能的增加,进程所需要的内存空间越来越大,进程空间很容易就突破了物理内存的实际大小,导致进程无法运行。

因此,为了解决内存不足的情况,缓和大程序与小内存之间的矛盾,扩充内存容量势在必行。

可以从物理和逻辑两方面来考虑扩充内存容量,物理扩容没啥技术含量,需要我们研究的自然是如何从逻辑上扩充内存容量。

所谓逻辑扩充,就是说实际上物理内存的容量没有发生改变,但是它能装的东西却变多了,使得用户看来似乎有一个比实际内存大得多的内存。

对内存的逻辑扩充技术主要有三种:覆盖技术、交换技术、以及虚拟内存(Virtual Memory),也称为虚拟存储器。事实上,这些逻辑扩充技术的核心理念都是一致的,研究的都是将哪个进程(或进程的某部分)暂时从内存移到外存(磁盘),以腾出内存空间供其他进程(或进程的某部分)占用。

覆盖(Overlay)和交换(Swapping)这两种存在于早期操作系统中的逻辑扩充技术现在已经成为历史,这里就简单介绍下:

前文说过,早期操作系统仅将内存空间分成两块:系统区(用于存放操作系统相关数据)和用户区(用于存放用户进程相关数据,内存中只能有一道用户程序,用户程序独占整个用户区空间,显然,内存空间容不下某个用户程序的现象常会发生。

覆盖技术(Overlay)的基本思想就是:程序运行时并非任何时候都要访问程序及数据的所有部分(尤其是大程序),因此可以把用户空间(内存)分成一个固定区和一个或多个覆盖区。

将程序经常活跃的部分放在固定区,其余部分按调用关系进行分段:首先将那些即将要用的段放在覆盖区,其他段放在外存(磁盘),在需要调用前由用户来安排特定的系统调用将这些放在外存中的段调入覆盖区,替换覆盖区中原有的段。

覆盖技术的缺点显而易见并且可以说是让人无法接受的,那就是覆盖技术是把解决内存空间不足的问题交给了用户。操作系统仅仅为用户提供将覆盖段调入内存的系统调用,但是必须由用户自己来说明覆盖哪个段、调入哪个段。

合着我用个电脑还得算着怎么才能让我的程序不崩溃?

OK,可以看出来,覆盖技术其实是用在同一个作业/进程的不同段之间的,那么不同的作业/进程之间怎么办呢?

这就是交换技术的适用场景。

交换技术(Swapping)的基本思想是:空闲进程/作业主要存储在外存(磁盘)上,当其中某个进程/作业需要运行的时候,就将其从磁盘中完整地调入内存,使该进程运行一段时间,然后再把它返回磁盘。所以说当进程/作业不运行的时候它们是不会占用内存的。

事实上,覆盖和交换技术分别解决了传统存储管理(物理内存管理)中存在的某个问题:

  • 覆盖技术打破了作业/进程必须一次性全部装入内存后才能开始运行(一次性)的限制
  • 交换技术打破了一旦作业被装入内存,就会一直驻留在内存中,直至作业运行结束(驻留性)的限制

当然了,Anyway,这两种逻辑扩充技术已经成为历史,虚拟内存技术才是目前的主流,它综合了这两种古老技术的特点,单枪匹马解决了传统存储管理中存在的这两个问题。

什么是虚拟内存

有了上述交换技术的铺垫,理解起虚拟内存来也就不那么陌生了。

当然了,在此之前,我一定要着重声明的是,不要把虚拟内存当作一个实际存在的东西,它是一门技术!和交换技术覆盖技术一样是一门用来逻辑扩充内存空间的技术!

虚拟内存技术基于一个非常重要的原理,局部性原理

1)时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行;如果某个数据被访问过,不久之后该数据很可能再次被访问。(因为程序中存在大量的循环)

2)空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问(因为很多数据在内存中都是连续存放的,并且程序的指令也是顺序地在内存中存放的)

基于这个局部性原理,在一个程序装入内存的时候,可以只将这个程序中很快会用到的部分装入内存,暂时用不到的部分仍然留在外存(磁盘),并且程序可以正常执行;

而在程序执行过程中,当 CPU 所需要的信息不在内存中的时候,由操作系统负责将所需信息从外存(磁盘)调入内存,然后继续执行程序;

如果调入内存的时候内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。

以上,就是虚拟内存技术。

如何实现虚拟内存技术

可以看见,虚拟内存允许一个作业/进程分多次调入内存,那如果采用连续分配方式,不方便实现,所以虚拟内存技术的实现是建立在不连续分配管理方式之上的。

传统的基本分页管理、基本分段管理、基本段页式管理和虚拟内存技术结合,分别称为请求分页管理(页式虚存系统)、请求分段管理(段式虚存系统)、请求段页式管理(段页式虚存系统)。

这几个概念非常容易混淆,其实很容易区分,记住这句话就 OK,摘自百度百科:

如果不具备请求调页、页面置换的功能,则称为基本分页管理(或称为纯分页管理),它不具有支持实现虚拟内存的功能,它要求把每个作业(进程)全部装入内存后方能运行。 请求分段存储管理也差不多,它建立在分段存储管理之上,但增加了请求调段、段置换功能。

请求调页、页面置换 和 请求调段、段置换概念差不多,这里以请求调页和页面置换为例解释下。

  • 在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存(磁盘)调入内存,然后继续执行程序(操作系统要提供请求调页的功能, 将内存中缺失的页面从磁盘调入内存 );
  • 若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到磁盘(操作系统要提供页面置换的功能, 将暂时用不到的页面换出磁盘)。

具体来说,在页式虚存系统中,每当 CPU 要访问的页面不在内存时,就会产生一个缺页中断,然后由操作系统的缺页中断处理程序来处理中断。此时,缺页的这个进程/作业就会被阻塞住,放入阻塞队列,调页完成后再将其唤醒,放回就绪队列。

  • 如果内存中有空闲块,则为该进程分配一个空闲块,将所缺的页面装入这个块中,并修改页表中相应的页表项。
  • 如果内存中没有空闲块,则由页面置换算法选择一个页面淘汰,若该页面在内存期间被修改过,则要将其写回外存,未修改过的页面不用写回外存。

可以看出来,这并不是一个简单的过程,基本分页管理中的简单页表已经无法胜任这样的工作。

我们还是先来回顾下基本分页管理的页表,它只有页号和块号两个字段:

请求分页管理的页表自然是会复杂不少的:

1)为了实现 “请求调页” 功能,操作系统需要知道每个页面是否已经调入内存,如果还没调入,那么也需要知道该页面在磁盘中存放的位置。

2)而当内存空间不够时,要实现 “页面置换” 功能,操作系统需要通过某些指标来决定到底换出哪个页面,有的页面没有被修改过,就不用浪费时间写回磁盘;有的页面修改过,就需要将磁盘中的旧数据覆盖。因此,操作系统也需要记录各个页面是否被修改的信息。

为此,请求分页管理的页表中添加了 4 个字段:

  • 状态位:该页面是否已调入内存
  • 访问字段:可记录该页面最近被访问过几次,或记录上次访问该页面的时间,供页面置换算法换出页面时参考
  • 修改位:该页面调入内存后是否被修改过
  • 外存地址:该页面在外存中的存放地址

页面置换算法也是一个很重要的内容,本来应该在这篇文章里一起写的,But 想到 “页面置换” 问题不仅仅是在虚拟内存中存在,在计算机设计的其他领域也会同样发生(比如多数计算机都会把最近使用过的 32 字节或者 64 字节存储块保存在一个或多个高速缓存中,当这些高速缓存存满后就必须选取一些块丢弃掉,以此来存入最新的使用过的存储块),所以决定后续单开一篇文章。

本文分享自微信公众号 - 飞天小牛肉(CS-Wiki),作者:飞天小牛肉

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-05-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 内存管理两部曲之物理内存管理

    先笼统地总结下内存管理到底是干啥的,下面这段话摘自《现代操作系统 - 第 3 版》:

    飞天小牛肉
  • Win32之内存管理之虚拟内存跟物理内存

      我们知道每个应用程序都有自己独立的4GB空间.  假设A进程的 地址123 存储了10  那么B进程的123地址 存储了20

    IBinary
  • 3.2 虚拟内存管理

    ②当大量作业要求运行时,由于内存不足以容纳所有作业,只能使少数作业先运行,导致多道程序度的下降。

    week
  • 3.2.8 虚拟内存管理

    多道程序并发执行不仅使进程之间共享了处理器,还同时共享了主存。然而,随着处理器需求的增长,进程的执行速度会以某种合理平滑的方式慢下来。但是,如果同时执行的进程太...

    week
  • windows虚拟内存管理

    内存管理是操作系统非常重要的部分,处理器每一次的升级都会给内存管理方式带来巨大的变化,向早期的8086cpu的分段式管理,到后来的80x86 系列的32位cpu...

    Masimaro
  • Linux虚拟内存管理

    Linux的内存管理分为 虚拟内存管理 和 物理内存管理,本文主要介绍 虚拟内存管理 的原理和实现。在介绍 虚拟内存管理 前,首先介绍一下 x86 CPU 内存...

    用户7686797
  • Java虚拟机内存管理(三)—内存异常

    Java 虚拟机作为运行 Java 程序抽象出来的计算机,具有内存管理的能力,像内存分配、垃圾回收等这些相关的内存管理问题,Java 虚拟机都会帮我们解决,所以...

    Wizey
  • Java虚拟机内存管理(一)—内存划分

    Java 虚拟机作为运行 Java 程序抽象出来的计算机,具有内存管理的能力,像内存分配、垃圾回收等这些相关的内存管理问题,Java 虚拟机都会帮我们解决,所以...

    Wizey
  • 粗谈Java虚拟机之内存管理

    线程私有,生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息...

    g小志
  • Spark内部原理之内存管理

    Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色。理解 Spark 内存管理的基本原理,有助于更好地开发 Spark...

    smartsi
  • 虚拟内存管理请求分页存储管理方式

    JavaEdge
  • 十问 Linux 虚拟内存管理 ( 一 )

    最近在做 MySQL 版本升级时( 5.1->5.5 ) , 发现了 mysqld 疑似“内存泄露”现象,但通过 valgrind 等工具检测后,并没发现类似的...

    陈福荣
  • 十问 Linux 虚拟内存管理 ( 二 )

    最近在做 MySQL 版本升级时( 5.1->5.5 ) , 发现了 mysqld 疑似“内存泄露”现象,但通过 valgrind 等工具检测后,并没发现类似的...

    陈福荣
  • ios内存管理-内存管理范围

    1、栈区(stack) — 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。 2、堆区(heap) — 一般由程序员分配释放,若程序员不释放...

    赵哥窟
  • 深入理解JVM虚拟机---JVM内存管理

    ​ 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念...

    俺也想起舞
  • 物理内存与虚拟内存

    物理内存就是你的机器本身内存了(如内存条的大小)。物理内存就是CPU的地址线可以直接进行寻址的内存空间大小。比如8086只有20根地址线,那么它的寻址空间就是1...

    一个会写诗的程序员
  • Android内存管理(三)内存管理基础

    CPU只能访问其寄存器(Register)和内存(Memory), 无法直接访问硬盘(Disk)。存储在硬盘上的数据必须首先传输到内存中才能被CPU访问。从访问...

    Anymarvel
  • Android内存管理(八)内存管理小结

    今天从操作系统的角度来闲聊一下代码开发过程中如何配合系统做内存管理。内存就是一块数据存储区域,是可被操作系统调度的资源。在多任务(进程)的OS中,内存管理尤为重...

    Anymarvel
  • MongoDB之内存管理

    在MongoDB中,加载各种依赖的lib到内存、管理客户端请求、元数据管理存储等工作都需要占用内存,但其实内存使用的大部分还是在存储引擎和客户端连接请求处理方面...

    AsiaYe

扫码关注云+社区

领取腾讯云代金券