内存管理学习笔记

内存管理

1. 内存共享特征

1.1. 逻辑地址与物理地址的区别

计算机在处理每一个程序时,就要为程序分配内存,每次分配内存时,都是先分配一个地址找到一块特定的内存区域,然后在这块特定的内存区域内进行内存的分配相对于这个特定内存区域的地址叫逻辑地址,计算机内存的的实际地址叫物理地址,物理地址是从0开始的连续区域。然而,当程序执行时,这个计算机程序在计算机内存中存储位置不一定是从0开始的。

1.2. 物理内存如何划分

物理内存层面,常常会把内存划分成不同的区域。可以划分成不同大小,也可以划分成相同大小。分区,分段存储方式一般是把内存划分成不同大小的块的,而分页则是划分成相同大小的块。

1.3. 存储管理的功能

实现逻辑地址向物理地址的转换。 实现多进程下的内存分配。 对各个用户的内存空间实施保护。 必要时,对逻辑主存进行扩充。

2. 内存管理新技术

2.1. 虚拟内存

一句话,就是外存当内存用,计算机在运行程序时,只是把程序的一部分代码放入内存运行,一部分放在内存之外的虚拟内存中,当有需要的时候,直接从虚拟外存中调入即可。减小内存压力。

2.2. ubantu下设置虚拟内存

3. 地址映射

地址映射这个地方我学到了很多c++的知识。主要可以联想c++程序的开发阶段。即编写,编译,连接,运行,这四个方面。

3.1. 编译时就确定地址映射关系

c++程序在编译时,就是给那些代码分配内存空间,(除了new分配的那些内存)。如果这个时候,就把逻辑地址转换为物理地址。运行的时候,就可以直接去物理内存拿数据了。但是,这样的话,那么,程序运行时的物理地址就固定了。

3.2. 静态地址映射

运行的时候,首先装入内存任意位置,接着发生地址转换。然后就把移动程序到转换后物理地址。

3.3. 动态地址映射

程序在运行时,当执行某条语句时,通过一个特定的地址转换机构实现逻辑地址到物理地址的转换。由硬件实现,可以弄个基址寄存器,逻辑地址加上基址寄存器得到物理地址。

4. 程序的逻辑组织

4.1. 一维

由于物理地址是一维连续的空间,所以把逻辑地址也划分成一维的。

4.2. 二维

把程序分为若干模块。一个程序有代码段,数据段,栈段,特别分段。我们编译时就把这些分开,每一段都有指向指向这个段的指针和段内偏移量。 好处呢 将不同代码区分开,更加方便管理。 动态链接,运行的时候需要段这个再去链接过来。

5. 管理方式

5.1. 分区

5.1.1. 概述

  • 动态分配实现地址映射
  • 分区分配机构

• 主存资源信息块

• 分区描述器和空闲队列

• 分区的分配与回收

5.1.2. 分配方式

  • 单一分区
  • 固定分区
  • 动态分区
  • 概述
  • 首次适应算法
  • 最佳适应算法
  • 最坏适应算法

5.1.3. 放置策略

5.1.4. 碎片问题和交换技术

某一时刻,内存中出现很多碎片,这些碎片互不相邻,所以内存回收时无法合并。同时,这些碎片的总容量足够大,但每一个碎片不能存储一个程序。这时,我们我们需要把这些碎片合并起来。移动已分配的内存空间到别的位置,使得碎片相邻,我们就可以合并碎片了。这种技术叫拼接技术 内存回收时拼接 当不够时再拼接 缺点: 移动已分配的内存,消耗大量cpu时间。成本太高。 当移动时,当前进程阻塞,对于对需要迅速及时响应的进程极不友好。 那么如何减少碎片化问题呢?接下来轮到分页管理登场。

5.2. 分页

5.2.1. 概述

我们把逻辑地址划分成不同的页,每一页放到物理内存的一个等大的块儿中,这样就能极大减少碎片化问题。这个和固定分区很像,但是固定分区并没有划分逻辑地址,如果分页的页数只有一页,那就和固定分区一样了。每一页的大小与物理内存快的大小相等,为2的n次幂。

5.2.2. 页面地址映射

页面如何映射到内存块,答案是采用页表。一个页表最基本要有两个字段:页号,物理内存快号。 逻辑地址组成:页号x,页内偏移量y 页表的存储: 1.可以放在内存中。这样访问一个数据就要访问两次内存。 2.放在cache中。提高查找速度,同时成本太高了。 3.一部分页表放在内存中,一部分放在cache中。访问数据中,首先查找cache中的页表(快),如果有,则去访问物理内存,直接拿数据。如果没有,则到内存中去查找,接着把条记录放到cache中,cache中满了咋办,一般淘汰最先进入的那条记录。 好像操作系统学过这玩意儿,当时考试还没回答上来。现在一想,cache中可以用队列来存这玩意儿,一旦队列满了,就出队列。

5.2.3. 请调策略

当访问的页面不在内存中,就要从虚拟内存中调入页面。如何判断页面在不在内存中?如果不在,在哪里? 1.第一个问题,我们可以给页表加入一个中断位i,i == 0表示在内存中,i!=0表示不在内存中。 2.第二个问题可以通过加一个外存地址字段。 访问页表大概的流程如下: 访问页表,查看中断位。如果中断位为0,说明页面在内存中,直接去物理内存中拿数据。如果中断位为不为0,发生缺页中断,cpu保护现场,阻塞当前进程,转入调页程序,将外存中的页面放入内存中,更改页面中断位为1,唤醒当前进程,当前进程去内存中拿数据。

5.2.4. 放置策略

5.2.5. 淘汰策略

从外存中索取页面放入内存中,内存空间已满,则需要淘汰内存某些页面。 抖动现象:要是淘汰算法没设计好,可能出现这样一种情况,内外存频繁交换,系统效率急剧下降,这种现象叫抖动或者颠簸。

  • 缺页率:程序页面总数s,在虚拟内存中页面的个数f,缺页率 =  f/s;
  • FIFO(先进先出算法): 队列。先淘汰最先进入的页面,因为他在内存中驻留最久。物理内存3个内存块。1入队列,2入队列,3入队列。4来了,发现队列满了,1出队列,4入队列。注意:4来了是为了置换1,所以与1的物理地址一样。但是再逻辑队列中,4实际上占用了3的位置。缺点:当队列满了以后,后面要不断的出队入队。一个出队的页面可能后面又要用到。改进:可以增加队列长度,增加缺页率。科学家Bleady发现缺页率随着内存大小增加而增加,真tm奇怪。
  • OPT(最佳适应算法):FIFO算法无非就是你出队列的页面将来可能由用到,那么先淘汰很久才使用或者不使用的页面。那么,怎么知道页面访问序列,这是个复杂的问题。这些算法都是实现知道了页面访问的情况,我们思考问题的时候,也可以这样,假设我们已经知道了一些条件,解决关键问题以后,再去靠近这个方案。科学家怎么解决这个问题:我过去的使用情况可不可以来预测未来使用情况,由过去的情况区预测将来。
  • 最久未使用淘汰算法(LRU):淘汰过去最久没有使用过的页面。实现方式:1.每一个页面增加一个时间字段,增加一个逻辑时间,当这个页面被访问过一次,就把逻辑时间复制到这个时间字段,淘汰的时候直接淘汰时间字段值最小的那个页面。2.利用栈实现每次访问一个页面,就把这个页面入栈,当访问的页与栈中页相同时,就把栈中这个页拿出,重新入栈。则栈底元素就是最久没有被访问的页。
  • 最不经常使用算法(LFU):把一段时间内使用次数最少的页淘汰。可对每一页设置一个计数器,一段时间内,这一页被访问一次,计数器就加一,最后淘汰计数器值最小的那个页。这和LRU算法有着本质区别,一段时间内使用最少的页不一定是最久未使用的页。

5.3. 分段

5.4. 段页式管理

posted @ 2020-05-06 22:32  FizzPu  阅读(201)  评论(0编辑  收藏  举报