1.什么是内存?

  1. 内存可存放数据。缓解CPU和硬盘之间的速度矛盾。

1.1 内存的呈现形式

  1. 在多道程序环境下,系统中会有多个程序并发执行,也就是说会有多个程序的数据需要同时放到内存中。那么如何区分各个程序的数据
  2. 放在哪里呢?
  3. 方案: 给内存的存储单元编地址。

1.2 寻址方式

内存中也有一个一个的“小房间”,每个小房间就是一个“存储单元”。
image.png

1.2.1 按字节寻址

  1. 每个存储单元大小为1 字节,即 1B ,也就是 8 bit(2进制数字)

1.2.2 按字寻址

  1. 如果字长是16位的计算机 “按字编址”,则每个存储单元大小为1个字,每个字的大小为2B,也就是16个二进制位.

1.3 知识滚雪球: 指令的工作原理

image.png

2.内存空间的分配与回收

3.1 内存管理 - 图5

2.1 连续分配管理方式

2.1.1 单一连续分配

image.png

2.1.2 固定分区分配

image.png

image.png
image.png

2.1.3 动态分区分配

2.1.3.1 动态分区分配概念

image.png

Q1: 系统要用什么样的数据结构记录内存的使用情况?

image.png

Q2:当很多个空闲分区都能满足需求时,应该选择哪个分区进行分配?

image.png

Q3: 如何进行分区的分配与回收操作?

简而言之,要对分区表或者分区链 及时更新有效区间。
2image.png
image.png

2.1.3.2 内部碎片与外部碎片

  • 内部碎片: 分配给某进程的内存区域中,如果偏大导致有些部分没有用上。
  • 外部碎片:是指内存中的某些空闲分区由于太小没有被利用上。

    2.1.3.3 动态分区分配算法

    ```java 又被称之为可变分区分配,这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的 大小正好适合进程的需要。

动态分区分配没有内部碎片,但是有外部碎片。 进程来的时候发现剩余内存空间的不够了。

  1. <a name="2tESU"></a>
  2. ##### 2.1.3.3.1 首次适应算法
  3. - [x] 算法思想

每次都从低地址开始查找,找到第一个能满足大小的空闲分区。

  1. - [x] 如何实现

空闲分区以地址递增的次序排列,每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。

  1. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/177460/1592234519945-3b7b3cab-9673-42e6-a744-a27c04dcae05.png#align=left&display=inline&height=375&margin=%5Bobject%20Object%5D&name=image.png&originHeight=750&originWidth=1334&size=522260&status=done&style=none&width=667)
  2. <a name="aoGjT"></a>
  3. ##### 2.1.3.3.2 最佳适应算法
  4. - [x] 算法思想

算法思想: 由于动态分区分配是一种连续分配方式,为各进程分配的空间必须是连续的一整片区域。因此为了保证当”大进程”到来时能有 连续的大空间,可以尽可能多地留下大片的空闲区.即,优先使用更小的空间

  1. - [x] 如何实现

空闲分区按照 容量 递增次序链接,每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。

  1. <a name="g1lnT"></a>
  2. ##### ![image.png](https://cdn.nlark.com/yuque/0/2020/png/177460/1592234851422-c98d2bf2-4d30-4433-b6c8-3a18d7410295.png#align=left&display=inline&height=375&margin=%5Bobject%20Object%5D&name=image.png&originHeight=750&originWidth=1334&size=602103&status=done&style=none&width=667)
  3. <a name="Ogav5"></a>
  4. ##### 2.1.3.3.3 最坏适应算法
  5. - [x] 算法思想

最坏适应算法 : 又称之为 最大适应算法 算法思想: 为了解决最佳使用算法的问题—即留下太多难以利用的小碎片,可以在每次分配时优先使用最大的连续空闲区,这样分配后 剩余的空闲区就不会太小,更方便使用。

  1. - [x] 如何实现

空闲分区按照容量递减次序链接。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。

  1. <a name="JqIfw"></a>
  2. ##### ![image.png](https://cdn.nlark.com/yuque/0/2020/png/177460/1592235136204-3aed0df7-baca-45cc-b105-c3065e9c7761.png#align=left&display=inline&height=375&margin=%5Bobject%20Object%5D&name=image.png&originHeight=750&originWidth=1334&size=684775&status=done&style=none&width=667)
  3. <a name="wj41Y"></a>
  4. ##### 2.1.3.3.4 邻近适应算法
  5. - [x] 算法思想

首次使用算法每次都从链表头部开始查找,这可能会导致低地址部分出现很多小的空闲分区,而每次分配查找时,都要经过这些 分区,因此也增加了查找的开销。如果每次都从上次查找结束的位置开始检索,就能解决此问题。

  1. - [x] 如何实现

空闲分区以地址递增的顺序排列(可)

  1. <a name="u85jh"></a>
  2. # ![image.png](https://cdn.nlark.com/yuque/0/2020/png/177460/1592322658228-5109f2bf-baff-46b1-b598-10e3aeb53128.png#align=left&display=inline&height=375&margin=%5Bobject%20Object%5D&name=image.png&originHeight=750&originWidth=1334&size=783824&status=done&style=none&width=667)
  3. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/177460/1592322668637-034ea77d-9106-474f-9fdf-8151bf8f7c0a.png#align=left&display=inline&height=375&margin=%5Bobject%20Object%5D&name=image.png&originHeight=750&originWidth=1334&size=779376&status=done&style=none&width=667)
  4. <a name="taer6"></a>
  5. ## 2.2 非连续分配管理方式
  6. 为用户进场分配的可以是一些分散的内存空间。
  7. <a name="yjg9i"></a>
  8. ### 2.2.1 基本分页存储管理
  9. <a name="HPB87"></a>
  10. #### 2.2.1.1 内存分页
  11. ```bash
  12. 将内存空间分为一个个大小相等的分区(比如: 每个分区4KB),每个分区就是一个"页框"(页框==页帧==内存块==物理块==物理页面)
  13. 每个页框有一个编号,即“页框号”,页框号从0开始.

image.png

2.2.1.2 进程逻辑地址空间分页

  1. 将进程的逻辑地址空间也分为与页框大小相等的一个个部分,每个部分称为一个“页”或者"页面"
  2. 每个页面也有一个编号,即“页号”,页号也是从0开始。

image.png
image.png

  1. 操作系统以页框为单位为各个进程分配内存空间。进程的每个页面分别放入一个页框中。也就是说,进程的页面与内存的页框有一一对应的关系。
  2. 各个页面不必连续存放,可以放到不相邻的各个页框中

2.2.1.3 实现方式-页表

image.png
image.png

2.2.1.3.1 页表项
  1. 页表由一个一个页表项组成,页表项包括页号和块号.

2.2.1.3.2 页表大小计算

2.2.1.4 如何实现地址转换