我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

传统存储管理存在的问题

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

什么是虚拟内存

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

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

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

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

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

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

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

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

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

如何实现虚拟内存技术

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

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

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

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

请求分段存储管理也差不多,它建立在分段存储管理之上,但增加了请求调段、段置换功能。

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

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

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

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

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

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

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

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

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

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

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

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

 

 

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

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

Java虚拟机内存管理该怎么理解

今天就跟大家聊聊有关Java虚拟机内存管理该怎么理解,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java虚拟机规范将物理内存(主内存和CPU中的缓存、寄存器)划分为程序计数器、Ja
2023-06-02

JVM内存管理之JAVA语言的内存管理详解

引言内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑。不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓狂的内存溢出和泄露的问题。可怕的事情还不只
2023-05-31

虚拟主机内存空间怎么管理

虚拟主机内存空间的管理可以通过以下几个方面来实现:1. 分配内存空间:虚拟主机可以通过内存分配算法,将可用的内存空间分配给不同的虚拟机实例。常见的分配算法有静态分配和动态分配两种。静态分配是指在启动虚拟主机时,将内存空间按比例分配给各个虚拟
2023-09-12

云计算虚拟化三部曲之一:CPU和内存虚拟化

我们知道,虚拟化技术是云计算的核心技术。通过虚拟化,可以切割计算、存储和网络资源的颗粒度。虚拟机可根据需要从池子里获取和释放各类型资源。

Java虚拟机内存管理知识有哪些

这篇文章主要讲解了“Java虚拟机内存管理知识有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java虚拟机内存管理知识有哪些”吧!0、Java 对内存的划分:Java虚拟机规范将物理内
2023-06-04

理解Linux内存管理:分配、释放和管理内存

Linux内存管理负责分配、释放和管理内存资源,采用虚拟内存和分页机制来实现,提供了丰富的内存分配和释放函数。
Linux内存2024-11-30

Spark内存管理

1、spark的一大特性就是基于内存计算,Driver只保存任务的宏观性的元数据,数据量较小,且在执行过程中基本不变,不做重点分析,而真正的计算任务Task分布在各个Executor中,其中的内存数据量大,且会随着计算的进行会发生实时变化,所以Executor
Spark内存管理
2019-06-05

C++ 内存管理中的内存池

内存池是一种 c++++ 技术,用于管理频繁分配和释放的特定大小对象。它使用预分配的内存块,提供比标准内存分配器更高的性能,特别是针对高度并发的应用程序。C++ 内存管理中的内存池内存池是一种用于优化内存分配和管理的 C++ 技术。它为频
C++ 内存管理中的内存池
2024-05-01

Linux内存管理之内存回收的示例分析

这篇文章主要介绍了Linux内存管理之内存回收的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.1 内存回收的目标不是所有的物理内存都可以参与回收的,比如要是把内核
2023-06-16

Python的内存管理

一直以为用Python、java这样的语言就不在需要关心内存使用的问题,但事情还是发生了。    前一段时间需要写一个应用,需要将用户删除的记录在文件中的偏移记录到另一个文件中,由于需要load的最大的数据文件也就1.2GB左右,而且系统的
2023-01-31

一步一图带你深入理解 Linux 虚拟内存管理

本文我们从虚拟内存地址开始聊起,一直到物理内存地址结束,包含的信息量还是比较大的。首先笔者通过一个进程的运行实例为大家引出了内核引入虚拟内存空间的目的及其需要解决的问题。

Python内存管理的原理

这篇文章主要介绍“Python内存管理的原理”,在日常操作中,相信很多人在Python内存管理的原理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python内存管理的原理”的疑惑有所帮助!接下来,请跟着小编
2023-06-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录