热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

操作系统对内存管理

在讲到进程与线程的区别时,一定会谈到的一点是:进程具有独立的地址空间,是内存分配的最小单元。那么这个地址空间指的是什么呢?地址空间是操作系统对物理内存的抽象,书上对地址空间的定义是:

在讲到进程与线程的区别时,一定会谈到的一点是:进程具有独立的地址空间,是内存分配的最小单元。那么这个地址空间指的是什么呢?
地址空间是操作系统对物理内存的抽象,书上对地址空间的定义是:“地址空间是一个进程可用于寻址的一套地址集合”。称为空间,所以是一个地址集合理解起来不难,最让人困惑的地方在于,为什么叫对内存的抽象,地址空间又是一种怎样的存在?

为什么叫内存的抽象?

如果看过设计模式的人可能会知道,设计模式中提到最多的概念之一就是抽象,纯虚的基类作为接口就是对各种派生类对象的抽象。调用接口的用户,并不知道内部如何实现,因此内部实现的方法可能也有多种。地址空间也可以这样理解,32位机上,创建进程时操作系统为进程分配4GB的独立地址空间,用户可以使用这4GB的独立地址空间。但是,反过来一想,给每个进程都分配4GB地址空间,对于8GB内存的计算机而言岂不也就能同时运行两个进程。对于现代计算机而言,这显然是不可能的。所以实际上,用户能使用的4GB地址空间并不是对应物理内存的4GB,具体怎么实现被封装了,所以叫内存抽象。

操作系统是如何通过地址空间来管理内存?

要理解操作系统对内存的管理,首先需要理解两个概念,交换技术和虚拟内存。

交换技术

计算机是多道程序设计,可以同时运行多个程序,然而内存大小有限,操作系统如何实现同时运行多个程序呢?
如下图,蓝色区域表示空闲的内存,绿色区域表示被某个进程占用的内存。刚开始装入A进程,然后装入B进程,再装入C进程。
对于这种模型而言,也是一种内存抽象,对于进程B而言假设其地址空间为0x0000-0xFFFF,对于其地址0x0000而言,对应的物理地址肯定不是0x0000,那应该是进程A的首地址。所以如果进程B要访问其首地址0x0000,就必须加上一个偏移量,而这样偏移量保存在一个基址寄存器中,除了基址寄存器还有一个界限寄存器防止访问越界。
再接着上面的说,如果这时候来了一个进程D,剩余的内存放不下进程D了,这时候可以选择将进程B交换出去,将进程B的数据保存到硬盘上,将进程D装入内存运行,如果CPU重新调度到进程B然后再采用同样的方式将某个进程交换出去,保存到硬盘上,把进程B装入内存中,这样的过程就叫交换技术。
内存交换

虚拟内存

交换技术似乎解决了多道程序运行的问题,但是实际上如果每次交换一整个进程的数据,CPU需要花费数秒的时间来处理,这显然是不能被容忍的。因此,需要提出虚拟内存的概念。
虚拟内存:每个进程拥有自己的地址空间,这个空间被分割成多个连续地址范围的页面,这些页面被映射到内存实际物理地址,但是操作系统给每个进程分配的实际物理地址远没有其地址空间那样大,因此任何时候都只有一部分页面映射到实际物理地址的页框(内存也被分成了一个个小块,称为页框)。没有映射到物理地址的页面上的数据被保存在硬盘上。当进程范围地址空间的某个地址时,操作系统将这个地址传给MMU,MMU中保存了该进程的所有页表,通过对应的地址查询页表,页表上记录了该地址是否映射到内存,如果是,则将映射的实际物理地址传给内存总线。如果没有映射到内存上,则发生缺页中断,将所缺页从硬盘交换到内存上,将内存中一个页框交换出去到硬盘上。因为,交换的数据少因此速度很快。而且,对于一个进程而言,常用的数据可能就集中在一小部分数据上,所以中断发生的次数也没有上面交换技术那样频繁。

内存管理总结(面试时怎么答)

虚拟内存
在提内存管理之前,需要先解释为什么需要内存管理?这是因为,现代计算机都是多道程序设计,计算机需要同时运行多个程序,那么需要将所有运行进程使用的数据放在内存上,但是计算机物理内存有限,因此需要将部分数据放在你硬盘上,当需要访问到这些硬盘上的数据时,操作系统将这些数据从硬盘上已到内存上。那么某个进程如何访问到该进程的数据,如何在硬盘和内存之间交换数据就需要进行内存管理。

数据访问
在创建进程时,操作系统为每个进程分配独立的地址空间,这个地址空间就是虚拟地址,对于32位系统而言是4GB。这个地址空间,被分为四段:文本段,数据段,堆段和栈段,栈一般在地址空间的顶部,在栈的顶部一小部分在程序启动的时候被装入进程的环境变量等。堆由低到高生长,栈由高向低生长。当程序访问该地址空间上的某个数据时,操作系统将这个虚拟地址传给MMU,MMU里面为每个进程维护了一张页表,这张表说明了每个进程的虚拟地址到实际物理地址的映射。实际上虚拟和地址和实际物理地址被分成了一个个小片,每个虚拟小片(页表)都映射到物理地址的一个小片(页框),通过一个基地址(页框号)加上一个偏移量就能访问到指定的字节。在MMU维护的页表上不仅有这个映射关系还有一些标志位,有个一在不在位表示访问的虚拟地址的数据是否在内存上,如果在那么MMU就将映射的实际物理地址传给CPU,如果不在则发生缺页中断,操作系统将该页数据从硬盘上交换到物理内存上,将物理内存的一页交换出去。但是应该交换哪一页呢?因此,有了许多的页面置换算法:先进先出算法,最近未使用算法,第二次机会页面算法,工作集时钟算法等。都是为了时交换的次数尽量减小,毕竟数据复制会很占用时间。

内存分配
上面已经阐述了一个进程如何访问内存数据的,接着说内存是如何分配的。那么对于每一个进程而言,操作系统又是如何给其分配实际物理内存空间的呢?操作系统内核为内存维护了一张空闲内存表,这张表一般来说是一个链表,为什么是链表,因为会经常发生从中间删除和插入,你又可以去扯链表的特点了。当分配内存时,操作系统去查询这张表,找到一块能容纳下的地方放进去,将剩余的返还给空闲表。如何找到这个容纳的地方有出现了多种算法:首次适配算法,第二次首次适配,最佳适配算法,最差适配算法。这四个算法你可以去细讲差别,首次适配第一次找到第一个大于需要的地址空间的块,每次都从表头开始找,第二次着从上次找到的位置开始找,最佳适配找一个和需要大小最接近比需要的大的,最差每次早最大的。实际上对于进程内部堆的分配,页可以采取同样类似的办法。

如果嫌不够,咋们还可以继续,对unix系统而言,fork会创建一个父进程的副本作为子进程的地址空间,他们会共享文本段。但是,复制数据太慢,因此出现了写时复制,一开始父子进程共享所有数据,只有当父进程或子进程需要修改某个数据时,才会该数据块创建副本,一般是虚拟地址一页。


推荐阅读
  • 使用Numpy实现无外部库依赖的双线性插值图像缩放
    本文介绍如何仅使用Numpy库,通过双线性插值方法实现图像的高效缩放,避免了对OpenCV等图像处理库的依赖。文中详细解释了算法原理,并提供了完整的代码示例。 ... [详细]
  • 非公版RTX 3080显卡的革新与亮点
    本文深入探讨了图形显卡的进化历程,重点介绍了非公版RTX 3080显卡的技术特点和创新设计。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
  • 本文将详细介绍如何在Linux操作系统中执行PHP脚本,包括环境配置、命令使用及验证方法。对于需要在Linux环境下开发或部署PHP应用的用户来说,这是一篇非常实用的文章。 ... [详细]
  • 探索电路与系统的起源与发展
    本文回顾了电路与系统的发展历程,从电的早期发现到现代电子器件的应用。文章不仅涵盖了基础理论和关键发明,还探讨了这一学科对计算机、人工智能及物联网等领域的深远影响。 ... [详细]
  • 2018年3月31日,CSDN、火星财经联合中关村区块链产业联盟等机构举办的2018区块链技术及应用峰会(BTA)核心分会场圆满举行。多位业内顶尖专家深入探讨了区块链的核心技术原理及其在实际业务中的应用。 ... [详细]
  • 本文详细介绍了网络存储技术的基本概念、分类及应用场景。通过分析直连式存储(DAS)、网络附加存储(NAS)和存储区域网络(SAN)的特点,帮助读者理解不同存储方式的优势与局限性。 ... [详细]
  • 深入浅出:Google工程师的算法学习指南
    通过Google工程师的专业视角,带你系统掌握算法的核心概念与实践技巧。 ... [详细]
  • 本文深入探讨了 Python 列表切片的基本概念和实际应用,通过具体示例展示了不同切片方式的使用方法及其背后的逻辑。 ... [详细]
  • 本文详细介绍了K-Medoids聚类算法,这是一种基于划分的聚类方法,适用于处理大规模数据集。文章探讨了其优点、缺点以及具体实现步骤,并通过实例进行说明。 ... [详细]
  • 本文探讨如何利用人工智能算法自动区分网页是详情页还是列表页,介绍具体的实现思路和技术细节。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
  • 深入理解Shell脚本编程
    本文详细介绍了Shell脚本编程的基础概念、语法结构及其在操作系统中的应用。通过具体的示例代码,帮助读者掌握如何编写和执行Shell脚本。 ... [详细]
author-avatar
嗯啊发送到法国_574
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有