引言

花了一段时间才把之前的笔记整理了一部分,平时太忙也没啥时间。今天开始整理内存管理部分的,内存管理部分大致分为三部分笔记,第一部分就是本篇内存管理基础,第二部分是虚拟内存,第三部分高速缓存。

一个程序在运行前,只是一个存储在磁盘上的可执行的二进制文件,包括可执行指令和数据。当程序运行时,这个二进制文件会被加载到内存中,指令和数据在执行时会被cpu从内存中加载到寄存器中,然后执行,可能会把执行结果再次存入内存中。数据以何种形式存在内存,如果为进程分配内存,进程退出如何回收,这个过程叫内存管理,接下来就详细介绍这个过程

早期无存储器抽象

无存储器抽象内存访问

用户程序直接操作物理内存的地址,比如将位置为1000的物理内存中的内容复制到REGISTER1

MOV REGISTER1,1000
物理内存模型

  • a模型早期的主机和微机,很少使用

  • b模型多用于嵌入式系统

  • c模型早期用于个人计算机

    a、c模型有一个bug,用户程序可能擦除操作系统内存,如果是这种无抽象的物理内存,同一时间只能运行一个进程。

多个程序运行-物理分块内存
  • 原理:内存被分块例如2kb一个块,在CPU内部有特殊寄存器来记录内存块的保护key,当程序运行时,会有一个PSW与寄存器中的对应,当不属于该内存块的程序访问时,PSW和寄存器中存的key将不一致,避免了程序访问别的程序的内存。简要示意图如下

  • 存在问题

    因为程序还是利用绝对路径访问内存,所以存在不同应用程序访问同一个内存块的问题,导致程序崩溃,下图的a和b加载到内存后内存结构为c,但是a的第一句跳转到24是没问题,但是b第一句跳转到28,但是内存地址28是程序a的。

    • IBM解决方案:静态重定位

      当加载b程序到16384时,所有访问地址都加上16384,比如JMP 28变成了JMP 16412,但是该方法不是一个通用的解决办法。此外,还需要程序提供额外的信息来标识哪些是地址。

存储抽象-地址空间

前边已经知道了无存储抽象,也就是直接使用物理内存的两个缺点

  1. 哪怕只有一个应用程序运行,操作系统内存也可能会被偶然或恶意破坏

  2. 多应用程序并发运行困难

地址空间概念
  • 概念:地址空间并不局限于存储,它是一个抽象的概念,电话号码是一个地址空间,ip也是,域名也是

  • 基地址和界限寄存器(动态重定位)

    • 使用基地址和界限寄存器时内存中进程的内存结构

    • cpu访问内存时,硬件会利用要访问的地址+base,然后判断是否大于base+limit的地址,如果大于那么访问就是越界的,产生错误并终止访问。

Swapping

如果内存足够大到可以容纳所有进程的代码和数据,那么地址空间加上硬件提供的动态重定位的方案或许已经可行,但是通常所有进程需要的内存超过存储可以提供的范围。

  • 标准Swapping

    • 原理:标准Swapping是通过换进程来重复利用内存空间,如下图首先内存只有A进程,接着B、C进程被创建或者换入内存,紧接着D进程需要运行,A被换出;当A再次被调度时,将B换出给A腾空间,A再次进入内存。

      但是A再次进入内存的时候,地址空间已经发生变化。所以,Swapping换入之后需要重新重定位,有两种方式:

1. 通过软件在载入的时候重定位

2. 通过硬件在运行的时候重定位(比较常用),基地址和界限寄存器就适用这种情况

内存压缩

内存因为进程的换入换出会产生一些内存空洞,这些内存空洞会导致内存浪费,因为这些空洞连续内存空间大小不足以容纳一个进程所需的空间。因此通过将所有进程占用的空间全部向下移动,就有可能将小的空洞连成一大块空闲内存。这种技术就叫内存压缩

进程内存大小分配问题

1. 固定大小,如果进程大小是固定不会改变,操作系统只需简单分配进程需要的大小

2. 数据段可能增长,此时有四种解决方法

1. 如果进程邻近有空闲内存,分配给进程

2. 如果进程邻近是其他进程,那么寻找一块更大的空闲内存,将进程迁移过去

3. 如果没有更大的空闲内存,那么尝试将邻近的进程交换出去

4. 如果进程无法增长内存并且交换区已经满了,那就挂起该进程直到有空闲内存(或者kill该进程)

为了提高内存分配的效率,满足大部分进程内存都会增长的场景。(a)系统在分配内存时为进程预留增长所需的空间;(b)如果进程有连个可增长的段,比如数据段和栈段,可以数据段从下往上分配,栈从上往下分配,如果内存不足时再增长内存。

页面Swapping

针对虚拟内存的,在下一部分详细介绍

空闲内存管理
  • Bitmaps

    • 原理:将内存分块成小的分配单元(可以是小到几个字或者大到几kb),然后用一个bitmap来记录哪些块已被使用,1代表使用,0代表空闲

    • 关键:内存单元大小的选择很关键,太小,bitmap太大,太大,会浪费有些空间

    • 缺点:当需要为进程分配内存时,内存管理系统需要遍历bitmap找出一段连续的空间,这个操作是很费时的

  • 空闲链表

    • 原理:用链表将以使用和未使用的内存连接起来,每个节点说明该节点是空闲的(H)还是已经使用(P),以及内存的起始位置和长度。

    • 例子,X代表要释放的进程,阴影部分代表空闲

1. a中x释放后,空闲链表P替换为H,该空间空闲

2. b和c的X释放后,两个相邻的空闲区域合并成一个区域,链表变短

3. d中X释放后三个链表节点合并成一个

连续内存分配算法

截止目前我们讨论的内存都是将内存作为连续内存为基础的,连续内存指的是我们分配给进程的内存在空间上是连续的,在下一部分中会介绍虚拟内存,将会看到,进程是可以被分配不连续的内存。拿上边图中的空闲链表做例子

  • 首次适配算法(first fit)

    内存管理器沿着链表搜索,直到找到一块足够大的空闲内存,假设现在要分配的内存为2,该算法将扫描链表,然后选择编号2的空闲块

  • 下次适配算法(next fit)

    和首次适配算法类似,只是搜索起始位置不同,首次适配算法是从头开始,而下次适配算法是从上一次分配的位置开始

  • 最佳适配算法(best fit)

    最佳适配算法从头开始搜索到结尾,找出最小的能容纳进程的空闲块,比首次适配算法慢。假设分配内存为2,则扫描全表发现编号5的空闲块最适合

  • 最差适配算法

    每次搜索最大的空闲内存块,来减少内存碎片,扫描全表,发现编号2的空闲块最大

  • 快速适配算法

    为常用分配内存大小建立不同的项,分项存储。和所有按空闲内存大小排序的算法一样,当进程内存释放或者换出时,查找相邻块判断是否可以合并是非常耗时的。

总结

上述总结了通过无存储器抽象到利用地址空间的抽象一步步解决从单进程到多进程问题、从进程需要小内存到内存无法容纳进程的问题。虽然现代计算机有更高级的虚拟内存技术,学习一个技术很好的方式是了解其发展历史,了解了历史,对理解一个技术的诞生有很好的帮助,因为可以知道为什么需要这个技术以及它解决的问题。在下一篇中将介绍虚拟内存技术。

操作系统内存管理_操作系统6内存管理基础相关推荐

  1. 操作系统饥饿现象_操作系统常见面试题

    1.进程的常见状态?以及各种状态之间的转换条件? 就绪:进程已处于准备好运行的状态,即进程已分配到除CPU外的所有必要资源后,只要再获得CPU,便可立即执行. 执行:进程已经获得CPU,程序正在执行状 ...

  2. 操作系统饥饿现象_操作系统心得体会

    一.操作系统 1.基本概念 操作系统简称OS,是配置在计算机硬件上的第一层软件,它能够有效的组织和管理计算机系统中的硬件和软件资源,合理的组织计算机工作流程,控制程序的执行,并向用户提供各种服务功能. ...

  3. jvm内存结构_聊聊JVM内存结构

    起因 我们经常会在面试的时候被问到JVM的内存结构,很多人会觉得这东西真的有用吗?也就是面试造火箭,入职拧螺丝.问这个就是纯粹来刁难人的吧. 但实际上,我们细想一下. •假设你不知道局部变量实际上属于 ...

  4. go 是常驻内存吗_图解 Go 内存分配器

    原标题:图解 Go 内存分配器 作者 | Ankur Anand 译者 | 闫亮 内存分配器一直是性能优化的重头戏,其结构复杂.内容抽象,涉及的数据结构繁多,相信很多人都曾被它搞疯了.本文将从内存的基 ...

  5. java 二维数组内存溢出_模拟Java内存溢出

    本文通过修改虚拟机启动参数,来剖析常见的java内存溢出异常(基于jdk1.8). 修改虚拟机启动参数 这里我们使用的是IDEA集成开发环境,选择Run/Debug Configurations 然后 ...

  6. linux 内存占用_分享Linux内存占用几个案例

    案例一 问题 最近一台 CentOS 服务器,发现内存无端损失了许多,free 和 ps 统计的结果相差十几个G,非常奇怪,后来Google了许久才搞明白. 分析 1.linux系统内存消耗主要有三个 ...

  7. java内存图解_图解JAVA内存模型(JMM:JAVA Memory Model)

    本文主要说明两个问题:JMM存在的意义是什么?JMM内部的工作原理是什么(重点讲一下并发编程模式下的数据访问一致性问题) . 1.为什么要使用JMM? 当我们刚开始接触JAVA语言的时候,就会被告知J ...

  8. linux 内存使用率_我的内存都去哪里了?| 美创运维日记

    在疫情期间,小编不得不待在家中远程办公.但变的是办公方式,不变的是美创运维的7*24小时不间断支持. 这不,一位客户发来了一条消息: 客户:张工,好像我这个数据库服务器的内存使用率有点高啊,你帮我看看 ...

  9. spark如何防止内存溢出_什么叫内存溢出?内存泄漏的定义又是什么?使用中如何避免?...

    一.基本概念 内存溢出:简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出. 内存泄漏:内存泄漏指程序运行过程中分配内存给临时变量,用 ...

最新文章

  1. mysql字节对齐_结构体字节对齐-位域及其对齐
  2. Microsoft Visual Studio 2005 Beta 2 下载地址
  3. Android——APK 在32bit/64bit平台 动态库问题
  4. 烂泥:【解决】VMware Workstation中安装ESXI5.0双网卡问题
  5. Linux执行yum不显示时间,Linux停的yum命令详解(朝花夕拾)
  6. 框架:SpringMVC的工作原理
  7. 全球及中国绝缘材料用沸石行业“十四五”前景规划及未来发展趋势报告2021年版
  8. jQuery小测试系列之jQuery基础知识
  9. 妈妈再也不怕我不会画漂亮的图了!
  10. 嵌入式开发概述(树莓派介绍)
  11. 前端学习(3169):react-hello-react之对props进行限制
  12. 《UTF-8与GB2312之间的互换》的改进
  13. 2×3卡方检验prism_卡方检验(最强总结)
  14. 达内python第二阶段月考_Python编程练习题二
  15. 【更新】Essential Studio for ASP.NET MVC更新至2018 v4(三)
  16. 下载安装tomcat和jdk,配置运行环境,与Intellij idea 2017关联
  17. 微信小程序 首页弹出用户协议
  18. 20位顶级设计师的桌面环境
  19. Logstash详解之——input模块
  20. orientdb java_OrientDB Java连接操作

热门文章

  1. MYSQL内置函数总结
  2. JS正则表达式使用方法及示例
  3. DFT-软件篇 from 陈新武
  4. C#中排序的多种实现方式
  5. FW: HTTP错误500显示具体的出错信息的方法
  6. 从数据库中存取二进制数据并显示
  7. Django 1.11 bootstrap样式文件无法加载问题解决
  8. WIN10运行软件,窗口不显示(移动到屏幕外无法复原)的解决办法 Label:Win10解决方案
  9. 解决paramiko获取远程脚本延时返回数据的问题
  10. IOS本地日志记录解决方案