内存管理

内存管理

操作系统的内存管理主要是做什么?

操作系统的内存管理主要负责内存的分配与回收(malloc 函数:申请内存,free 函数:释放内存),另外地址转换也就是将逻辑地址转换成相应的物理地址等功能也是操作系统内存管理做的事情。

###常见的内存管理机制和几种方式

简单分为连续分配管理方式非连续分配管理方式这两种。

连续分配管理方式是指为一个用户程序分配一个连续的内存空间,常见的如块式管理。同样地,非连续分配管理方式允许一个程序使用的内存分布在离散或者说不相邻的内存中,常见的如页式管理段式管理

  1. 块式管理:远古时代的计算机操系统的内存管理方式。将内存分为几个固定大小的块,每个块中只包含一个进程。如果程序运行需要内存的话,操作系统就分配给它一块,如果程序运行只需要很小的空间的话,分配的这块内存很大一部分几乎被浪费了。这些在每个块中未被利用的空间,我们称之为碎片。

  2. 页式管理:把主存分为大小相等且固定的一页一页的形式,页较小,相对相比于块式管理的划分力度更大,提高了内存利用率,减少了碎片。页式管理通过页表对应逻辑地址和物理地址。

  3. 段式管理:页式管理虽然提高了内存利用率,但是页式管理其中的页实际并无任何实际意义。段式管理把主存分为一段段的,每一段的空间又要比一页的空间小很多 。但是,最重要的是段是有实际意义的,每个段定义了一组逻辑信息,例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。段式管理通过段表对应逻辑地址和物理地址。

  4. 段页式管理机制:段页式管理机制结合了段式管理和页式管理的优点。简单来说段页式管理机制就是把主存先分成若干段,每个段又分成若干页,也就是说段页式管理机制中段与段之间以及段的内部的都是离散的。

快表和多级页表

页表管理机制中有两个很重要的概念:快表和多级页表,这两个东西分别解决了页表管理中很重要的两个问题

在分页内存管理中,很重要的两点是:

  1. 虚拟地址到物理地址的转换要快。

  2. 解决虚拟地址空间大,页表也会很大的问题。

快表

为了解决虚拟地址到物理地址的转换速度,操作系统在页表方案基础之上引入了快表来加速虚拟地址到物理地址的转换。我们可以把块表理解为一种特殊的高速缓冲存储器(Cache),其中的内容是页表的一部分或者全部内容。作为页表的 Cache,它的作用与页表相似,但是提高了访问速率。由于采用页表做地址转换,读写内存数据时 CPU 要访问两次主存。有了快表,有时只要访问一次高速缓冲存储器,一次主存,这样可加速查找并提高指令执行速度。

使用快表之后的地址转换流程是这样的:

  1. 根据虚拟地址中的页号查快表;

  2. 如果该页在快表中,直接从快表中读取相应的物理地址;

  3. 如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表项添加到快表中;

  4. 当快表填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。

看完了之后你会发现快表和我们平时经常在我们开发的系统使用的缓存(比如 Redis)很像,的确是这样的,操作系统中的很多思想、很多经典的算法,你都可以在我们日常开发使用的各种工具或者框架中找到它们的影子。

多级页表

引入多级页表的主要目的是为了避免把全部页表一直放在内存中占用过多空间,特别是那些根本就不需要的页表就不需要保留在内存中。多级页表属于时间换空间的典型场景,具体可以查看下面这篇文章

  • 多级页表如何节约内存:https://www.polarxiong.com/archives/多级页表如何节约内存.html

总结

为了提高内存的空间性能,提出了多级页表的概念;但是提到空间性能是以浪费时间性能为基础的,因此为了补充损失的时间性能,提出了快表(即 TLB)的概念。不论是快表还是多级页表实际上都利用到了程序的局部性原理,局部性原理在后面的虚拟内存这部分会介绍到。

分页机制和分段机制的共同点和区别

  1. 共同点

  • 分页机制和分段机制都是为了提高内存利用率,较少内存碎片。

  • 页和段都是离散存储的,所以两者都是离散分配内存的方式。但是,每个页和段中的内存是连续的。

区别

  • 页的大小是固定的,由操作系统决定;而段的大小不固定,取决于我们当前运行的程序。

  • 分页仅仅是为了满足操作系统内存管理的需求,而段是逻辑信息的单位,在程序中可以体现为代码段,数据段,能够更好满足用户的需要。

逻辑(虚拟)地址和物理地址

我们编程一般只有可能和逻辑地址打交道,比如在 C 语言中,指针里面存储的数值就可以理解成为内存里的一个地址,这个地址也就是我们说的逻辑地址,逻辑地址由操作系统决定。物理地址指的是真实物理内存中地址,更具体一点来说就是内存地址寄存器中的地址。物理地址是内存单元真正的地址。

CPU 寻址了解吗?为什么需要虚拟地址空间?

现代处理器使用的是一种称为虚拟寻址(Virtual Addressing)的寻址方式。使用虚拟寻址,CPU 需要将虚拟地址翻译成物理地址,这样才能访问到真实的物理内存。实际上完成虚拟地址转换为物理地址转换的硬件是 CPU 中含有一个被称为内存管理单元(Memory Management Unit, MMU)的硬件。如下图所示:

为什么要有虚拟地址空间呢?

先从没有虚拟地址空间的时候说起吧!没有虚拟地址空间的时候,程序都是直接访问和操作的都是物理内存。但是这样有什么问题呢?

  1. 用户程序可以访问任意内存,寻址内存的每个字节,这样就很容易(有意或者无意)破坏操作系统,造成操作系统崩溃。

  2. 想要同时运行多个程序特别困难,比如你想同时运行一个微信和一个 QQ 音乐都不行。为什么呢?举个简单的例子:微信在运行的时候给内存地址 1xxx 赋值后,QQ 音乐也同样给内存地址 1xxx 赋值,那么 QQ 音乐对内存的赋值就会覆盖微信之前所赋的值,这就造成了微信这个程序就会崩溃。

总结来说:如果直接把物理地址暴露出来的话会带来严重问题,比如可能对操作系统造成伤害以及给同时运行多个程序造成困难。

通过虚拟地址访问内存有以下优势:

  • 程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。

  • 程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。

  • 不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程或操作系统使用的物理内存。

虚拟内存

什么是虚拟内存(Virtual Memory)?

这个在我们平时使用电脑特别是 Windows 系统的时候太常见了。很多时候我们使用点开了很多占内存的软件,这些软件占用的内存可能已经远远超出了我们电脑本身具有的物理内存。为什么可以这样呢?*正是因为*虚拟内存的存在,通过虚拟内存可以让程序可以拥有超过系统物理内存大小的可用内存空间。另外,虚拟内存为每个进程提供了一个一致的、私有的地址空间,它让每个进程产生了一种自己在独享主存的错觉(每个进程拥有一片连续完整的内存空间)。这样会更加有效地管理内存并减少出错。

虚拟内存是计算机系统内存管理的一种技术,我们可以手动设置自己电脑的虚拟内存。不要单纯认为虚拟内存只是“使用硬盘空间来扩展内存“的技术。虚拟内存的重要意义是它定义了一个连续的虚拟地址空间,并且把内存扩展到硬盘空间。推荐阅读:《虚拟内存的那点事儿》

维基百科中有几句话是这样介绍虚拟内存的。

虚拟内存使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如 RAM)的使用也更有效率。目前,大多数操作系统都使用了虚拟内存,如 Windows 家族的“虚拟内存”;Linux 的“交换空间”等。From:https://zh.wikipedia.org/wiki/虚拟内存

局部性原理

要想更好地理解虚拟内存技术,必须要知道计算机中著名的局部性原理。另外,局部性原理既适用于程序结构,也适用于数据结构,是非常重要的一个概念。

局部性原理是虚拟内存技术的基础,正是因为程序运行具有局部性原理,才可以只装入部分程序到内存就开始运行。

以下内容摘自《计算机操作系统教程》 第 4 章存储器管理。

早在 1968 年的时候,就有人指出我们的程序在执行的时候往往呈现局部性规律,也就是说在某个较短的时间段内,程序执行局限于某一小部分,程序访问的存储空间也局限于某个区域。

局部性原理表现在以下两个方面:

  1. 时间局部性:如果程序中的某条指令一旦执行,不久以后该指令可能再次执行;如果某数据被访问过,不久以后该数据可能再次被访问。产生时间局部性的典型原因,是由于在程序中存在着大量的循环操作。

  2. 空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内,这是因为指令通常是顺序存放、顺序执行的,数据也一般是以向量、数组、表等形式簇聚存储的。

时间局部性是通过将近来使用的指令和数据保存到高速缓存存储器中,并使用高速缓存的层次结构实现。空间局部性通常是使用较大的高速缓存,并将预取机制集成到高速缓存控制逻辑中实现。虚拟内存技术实际上就是建立了 “内存一外存”的两级存储器的结构,利用局部性原理实现髙速缓存。

虚拟存储器

?‍?面试官:都说了虚拟内存了。你再讲讲虚拟存储器把!

?

这部分内容来自:王道考研操作系统知识点整理。

基于局部性原理,在程序装入时,可以将程序的一部分装入内存,而将其他部分留在外存,就可以启动程序执行。由于外存往往比内存大很多,所以我们运行的软件的内存大小实际上是可以比计算机系统实际的内存大小大的。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换到外存上,从而腾出空间存放将要调入内存的信息。这样,计算机好像为用户提供了一个比实际内存大的多的存储器——虚拟存储器

实际上,我觉得虚拟内存同样是一种时间换空间的策略,你用 CPU 的计算时间,页的调入调出花费的时间,换来了一个虚拟的更大的空间来支持程序的运行。不得不感叹,程序世界几乎不是时间换空间就是空间换时间。

虚拟内存的技术实现

虚拟内存的实现有以下三种方式:

  1. 请求分页存储管理:建立在分页管理之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分页是目前最常用的一种实现虚拟存储器的方法。请求分页存储管理系统中,在作业开始运行之前,仅装入当前要执行的部分段即可运行。假如在作业运行的过程中发现要访问的页面不在内存,则由处理器通知操作系统按照对应的页面置换算法将相应的页面调入到主存,同时操作系统也可以将暂时不用的页面置换到外存中。

  2. 请求分段存储管理:建立在分段存储管理之上,增加了请求调段功能、分段置换功能。请求分段储存管理方式就如同请求分页储存管理方式一样,在作业开始运行之前,仅装入当前要执行的部分段即可运行;在执行过程中,可使用请求调入中断动态装入要访问但又不在内存的程序段;当内存空间已满,而又需要装入新的段时,根据置换功能适当调出某个段,以便腾出空间而装入新的段。

  3. 请求段页式存储管理

这里多说一下?很多人容易搞混请求分页与分页存储管理,两者有何不同呢?

请求分页存储管理建立在分页管理之上。他们的根本区别是是否将程序全部所需的全部地址空间都装入主存,这也是请求分页存储管理可以提供虚拟内存的原因,我们在上面已经分析过了。

它们之间的根本区别在于是否将一作业的全部地址空间同时装入主存。请求分页存储管理不要求将作业全部地址空间同时装入主存。基于这一点,请求分页存储管理可以提供虚存,而分页存储管理却不能提供虚存。

不管是上面那种实现方式,我们一般都需要:

  1. 一定容量的内存和外存:在载入程序的时候,只需要将程序的一部分装入内存,而将其他部分留在外存,然后程序就可以执行了;

  2. 缺页中断:如果需执行的指令或访问的数据尚未在内存(称为缺页或缺段),则由处理器通知操作系统将相应的页面或段调入到内存,然后继续执行程序;

  3. 虚拟地址空间:逻辑地址到物理地址的变换。

页面置换算法的作用?常见的页面置换算法有哪些?**

这个题目经常作为笔试题出现,网上已经给出了很不错的回答,我这里只是总结整理了一下。

地址映射过程中,若在页面中发现所要访问的页面不在内存中,则发生缺页中断 。

缺页中断就是要访问的不在主存,需要操作系统将其调入主存后再进行访问。在这个时候,被内存映射的文件实际上成了一个分页交换文件。

当发生缺页中断时,如果当前内存中并没有空闲的页面,操作系统就必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。用来选择淘汰哪一页的规则叫做页面置换算法,我们可以把页面置换算法看成是淘汰页面的规则。

  • OPT 页面置换算法(最佳页面置换算法):最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。一般作为衡量其他置换算法的方法。

  • FIFO(First In First Out) 页面置换算法(先进先出页面置换算法): 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰。

  • LRU (Least Currently Used)页面置换算法(最近最久未使用页面置换算法):LRU算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 T,当须淘汰一个页面时,选择现有页面中其 T 值最大的,即最近最久未使用的页面予以淘汰。

  • LFU (Least Frequently Used)页面置换算法(最少使用页面置换算法): 该置换算法选择在之前时期使用最少的页面作为淘汰页。

虚拟存储器管理c语言_内存管理;虚拟内存相关推荐

  1. JVM内存管理------JAVA语言的内存管理概述

    转载自  JVM内存管理------JAVA语言的内存管理概述 引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上 ...

  2. C语言与JAVA内存管理_C语言动态内存管理和动态内存分配

    动态内存管理同时还具有一个优点:当程序在具有更多内存的系统上需要处理更多数据时,不需要重写程序.标准库提供以下四个函数用于动态内存管理: (1) malloc().calloc() 分配新的内存区域. ...

  3. C语言的内存管理(堆,栈,代码段,数据段)

    C语言的内存管理(堆,栈,代码段,数据段) 一.几个基本概念 在C语言中,关于内存管理的知识点比较多,如函数.变量.作用域.指针等,在探究C语言内存管理机制时,先简单复习下这几个基本概念: 1.变量: ...

  4. 6.Python深入_内存管理

    Vamei博客地址:http://www.cnblogs.com/vamei/p/3232088.html 哈,这次是完完全全照搬大神的了 语言的内存管理是语言设计的一个重要方面.它是决定语言性能的重 ...

  5. linux内存管理(一)-内存管理架构

    文章目录 一.内存管理架构 二.虚拟地址空间布局架构 2.1内核地址空间布局 2.2用户地址空间布局 三.物理内存体系架构 3.1 正常内存 3.2 设备内存 四.内存结构 五.内存模型 六.虚拟地址 ...

  6. 【Linux 内核 内存管理】内存管理架构 ② ( 用户空间内存管理 | malloc | ptmalloc | 内核空间内存管理 | sys_brk | sys_mmap | sys_munmap)

    文章目录 一.用户空间内存管理 ( malloc / free / ptmalloc / jemalloc / tcmalloc ) 二.内核空间内存管理 1.内核内存管理系统调用 ( sys_brk ...

  7. 4.4OC10-内存管理2-set方法的内存管理

    4.4OC10-内存管理2-set方法的内存管理 例一: main.m  // //  main.m //  OC10-内存管理2-set方法的内存管理 // //  Created by qwz o ...

  8. C语言动态内存管理和动态内存分配函数

    给变量分配内存空间可分为静态内存分配和动态内存分配. 静态内存分配属于编译时给变量分配的空间,动态分配属于在程序运行时给变量分配的空间 静态分配属于栈分配,动态分配属于堆分配 运行效率上,静态内存比动 ...

  9. 操作系统知识点_内存管理

    2.内存管理: 内存管理方式: 块式管理:主存分为一大块一大块.易于管理,浪费太大: 页式管理:主存分为一页一页的,每一页比一块要小得多.显然其空间利用率比块式高很多.分页用户不可见. 段式管理:二维 ...

最新文章

  1. 修图动口不动手,有人把StyleGAN和CLIP组了个CP,能听懂修图指令那种
  2. Gitlab VM安装过程
  3. python中文字符串编码_浅谈python下含中文字符串正则表达式的编码问题
  4. 【CMake】Android Studio 中使用 CMake 编译单个 C++ 源文件 ( 常用的 CMake 命令解析 )
  5. ACM竞赛学习整理--Gauss求解POJ1166
  6. boost::mp11::mp_if相关用法的测试程序
  7. 设计面向游戏的人工智能(三):战术和战略人工智能 (AI)
  8. MySQL 的 bug 必须修复吗?
  9. Apache Cassandra和低延迟应用程序
  10. 共享两个有用的网页布局表格 【有用】
  11. MySQLi学习笔记 :二(  排序查询,聚合函数,分组查询,分页查询) 约束     多表之间的关系   范式     数据库的备份和还原
  12. 图解TCPIP-TCP IP
  13. NHibernate官方文档中文版——批量插入(Batch inserts)
  14. iptables转发基础
  15. EasyX实现按钮效果
  16. 如何在html中插入表情包,怎么把表情包插入word
  17. 小程序源码:微信零钱模拟器
  18. 1. 2020年《DeepMind&UCL深度学习讲座》第1讲:机器学习和AI入门【中文字幕】
  19. Private VLAN 与Switchport Protected
  20. 什么表示计算机存储信息的能力以字节为单位,大学计算机基础考试判断.doc

热门文章

  1. java创建 xml_java创建和读取xml
  2. hdu3949(线性基,求第k小的异或和
  3. java se基础巩固实例,Java SE基础巩固(十五):lambda表达式
  4. mysql中sysdate(),curdate(),curtime(),now()
  5. lstm原理及实现_LSTM原理
  6. windows无法打开所需的文件C:\Sources\install.wim。
  7. JAVA 不足N位后面补XX符号
  8. java 中怎么比较两个时间相差的秒数
  9. Maven技巧和窍门:高级Reactor选项
  10. 第一个SSCLI范例:echo的调试问题