内存管理

内存分为:  物理内存 和  虚拟内存。

先看物理内存:

 

存储器的层次结构:

  寄存器  高速缓存   主存   磁盘缓存(也是主存的一部分)   磁盘

程序的装入和链接

  程序要想运行,需要先将程序加载到内存当中。

  程序的装入:

    绝对装入方式:用户程序在编译后,产生绝对地址(物理地址)。(只能将程序装载到指定的位置)只加载单道程序。

    可重定位装入方式:在装入到内存时,将程序中的指令和数据的地址进行修改为实际的物理地址,静态重定位。多道程序。

    动态运行时的装入方式:不是在装入的时候,将逻辑地址转为物理地址,而是在程序执行的时候才会进行地址的转换。

连续分配存储管理方式:

  用户程序装入内存,分配一定大小的内存空间。

  单一连续分配:(只装配单个程序,分为系统区和用户去。系统区放在内存的地址部分,用户区就放一道程序)

  固定分区分配:(为了装载多道程序,将内存的用户空间分为若干个固定大小的分区,每个的大小可以相等也可以不等)(分区的大小是不改变的)

  动态分区分配:

    数据结构:空闲分区表: 分区号、分区大小、分区初始地址 ;  空闲分区链。

    动态分区分配算法:基于顺序搜索的动态分区分配算法

    分区分配操作:内存的分配与回收

    基于顺序搜索的动态分区分配算法:(主要就是进行程序的加载,为程序分配好内存)

    首次适应算法: 将空间分区链以地址递增的次序链接,分配内存时,从链首地址开始,也就是从内存的低地址开始,找到大小满足的空闲分区后,就从将一部分内存给请求者,剩下的仍然在空闲分区链中。低地址的空间分区大小不断变小,每次又是从低地址开始查找,增加了搜索合适的空闲分区的时间。

    循环首次适应算法:不是每次从链首开始查找合适的空闲分区,而是从上次使用的空闲分区的下一个空闲分区开始进行查找。容易造成内存中缺少大的空闲分区

    最佳适应:将空闲分区按照容量以从小到大的顺序组成空闲分区链。每次都是分配最小的且最能满足要求的空闲分区给请求者。

    最坏适应:空闲分区大小按照从大到小的顺序组成空闲分区链,总是挑选最大的空闲区,从中分配内存给请求者

      基于索引搜索的动态分区分配算法:

    快速适应:将空闲分区按照容量大小进行分类,每类的空闲分区建立一个空闲分区链表,在内存中设立一张管理索引表。用来管理多个索引链表。

    伙伴系统:要求已分配分区和空闲分区的大小都是2的k次幂。当请求内存大小为m时,则找大小为2的i次幂大于等于m, 2的 i-1 次幂小于等于m的空闲分区,如果没有,则找2的i+1幂大小的分区,然后将这个分区,分为大小相等的两部分,一部分用于分配内存,一部分放到空闲列表中。如果2的i+1次幂大小的空闲内存分区也没有,就继续往上找。

(上面两种算法都需要建立一个  管理索引表)

    哈希算法:构建以空闲分区大小为关键字的哈希表,快速得到空闲分区。

  动态可重定位分区分配:

    (连续分配方式要求分配的是连续的内存空间,这样会造成有很多不连在一起的内存空闲分区,但他们的总容量大于请求的内存大小,每个分区的容量小于请求的大小 ,为了解决这个问题,就需要移动内存分区,将空闲分区连在一起  )

    动态重定位:程序装入内存后的地址仍然是逻辑地址,当程序指令执行的时候才会将逻辑地址转为物理地址。

    加入了一个重定位寄存器,用来存储程序在内存中的起始地址。程序执行时的地址由 重定位寄存器中的起始地址和相对地址来决定。

 

Swapping对换:

  为什么要有对换:

  把内存中的暂时不能运行的进程或者暂时不用的程序和数据换出到外存上(Linux中是在磁盘有一个swap分区),腾出内存空间,来装载进的程序。

  对换的类型:

    整体对换:以进程为单位

    部分对换:以进程的一个“页面”或者“分段为单位”

  对换空间的管理:

    磁盘空间分为文件区和对换区两部分。

   

离散分配方式: 分页存储管理方式、分段存储管理方式、段页式存储管理方式

  允许进程分散的装入不相邻的内存分区中,提高内存空间的利用率。

分页存储管理方式:

分页存储管理的基本方法:

  页面和物理块。将进程的逻辑地址空间分为若干个页,将内存的物理地址分为若干个块。为进程分配内存时,将进程中的页装到物理块中,最后一页通常装不满一块,形成不可利用的碎片,称之为 “页内碎片”。

  页面大小的选择:页面过小,会导致页表过长,占用大量内存;页面过大,会使得页内碎片变大。

  地址结构: 分页地址中的地址结构分为: 页号和偏移量(页内偏移量)

  页表: 为了实现页号到物理块的映射,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。

地址变换结构:  为了将用户地址空间中的逻辑地址转换为内存空间中的物理地址。   逻辑地址由页号和页内便宜地址组成,因此这里的地址转换主要就是将页号转换为实际的物理块,借助于页表来实现。

两级和多级页表: 页表占用的内存很大时,很难找到一片连续的内存空间进行存储。

  两级页表:对页表也进行分页

  多级页表:采用两级页表的时候,如果外层的页表所占内存仍然很大,就继续添加一层页表。

反置页表:

 

分段存储管理方式:

  (面试的时候,懵了啊!!!)

(分页存储管理是将进程得逻辑地址进行分页,每个页的大小固定,那么分段的段是什么意思呢?? )

分段存储管理方式的引入:

  信息共享:

  信息保护:信息共享和信息保护 通过都是以信息的逻辑单位共享的,比如共享某个函数。而这个函数可能会占用多个页,采用分页存储存储需要操作多个页,用分段存储的方式只需要操作一个段就可以。

  动态增长:

  动态链接:程序运行时,将主程序和立即需要用到的目标程序装入内存,在程序运行过程中,当需要用到某个目标程序时,才将该段(目标程序)调入内存并进行链接。

分段系统的基本原理:

  分段: 作业的地址空间(进程的逻辑空间)被分为若干个段,每个段定义一组逻辑信息。段地址结构:段号 和 段内地址。

    (怎么分的???? 编译程序自动转换根据源程序的情况产生若干个段!!)

  段表: 类似于页表。 完成逻辑地址到物理地址的映射。段表存储的是段在内存中的起始地址和段的长度。

    地址变换机构:完成逻辑地址到物理地址的变换。

分段和分页的主要区别: (都采用的离散分配方式)

  1)页是信息的物理单位,采用分页存储管理方式是为了提高内存的利用率,没有逻辑意义。 段是信息的逻辑单位,分段存储是为了更好的满足用户的需要。

  2)页的大小固定,由系统决定,页的地址分为 页号和页内地址。段的长度不固定,取决于用于的程序。

信息共享:

  分段系统的一个突出优点,就是易于实现段的共享,允许若干个进程共享一个或多个分段。

段页式存储管理方式:

  分页系统以页面为内存分配的基本单位,能有效的提高内存的利用率。分段系统以段为内存分配的基本单位,能更好的满足用户的需要。

  将用户的程序分为若干个段,然后将段分为若干页。

  地址结构变为: 段号、段内页号、页内地址

 

 

虚拟存储器:从逻辑上实现了对内存容量的扩充!!!!

  (内存取决于地址总线的位数,相当于每个进程的都占用所有的内存空间!!!)

 考虑两种情况:

    1)程序很大,超过了内存空间,不能一次全部导入进来

    2)大量的程序要求运行,内存不足以容纳这么多的程序

  (本质都是内存不足。)

  虚拟存储器特征:

    多次性: 无须一次性将所有的程序都加载到内存,可以当程序执行到未加载内存的那部分程序时,将那部分程序加入到内存中来。

    对换性:可以将暂时用不到的代码从内存移到外存。

    虚拟性:使得每个进程都感觉好像拥有整个内存空间。

 

虚拟存储器的实现方式: 分页请求系统、请求分段系统

请求分页存储管理方式:

  在基本分页系统的基础之上,增加了请求调页功能和页面置换功能。

  请求分页的硬件支持:

    请求页表机制:(在基本的页表上面增加了4个字段,基本的页表只有页号和物理块号,用于实现逻辑地址和物理地址的映射 )

             增加了: 状态位 :表示该页是否在内存中

                 访问字段 : 记录本页在一段时间内被访问的次数,或者本页最近有多长时间未被访问,在页面置换时会用到。

                 修改位: 标识该页内容在内存中有没有被修改,如果被修改需要将该页写回到外存。

                 外存地址: 该页外外存上的地址,在加载这个页进内存的时候会用到。

     缺页中断机制:当所访问的页面不在内存时,产生缺页中断,请求os 将所缺页调入内存。

             

页面置换算法:

  在进程运行过程中,如果发现某一个没有在内存中,就会触发缺页中断,将页加入到内存中,如果内存满了,需要将内存中暂时不用的数据置出到外存中,( 比如linux的磁盘的中就有一个 swap分区。) 将哪个页面置出,由页面置换算法来决定。

  

先进先出(FIFO): 淘汰最先进入内存的页面

最近最少使用 LRU:   1)通过移位寄存器硬件来实现  2)通过双向列表数据结构来实现

  淘汰最长时间未使用的页面

最少使用LFU:为每个页面设置一个移位寄存器,每个一定时间,将里面值右移一次。 (与LRU的区别是什么?????)

  淘汰一段时间内,使用次数最小的页面

Clock置换算法:

  简单的Clock置换算法:为每页设置一位访问位,将内存中的所有页面通过指针链接成一个循环队列。当某页被访问时,访问位被置1. 发生置换的时候,如果页的访问位为0就置出,为1,置为0,暂时不置出。 (也被称为最近未使用算法)

  改进型Clock置换算法: 在置换页面时,考虑页面在内存中有没有被修改过!优先淘汰最近未被访问,又未被修改的页面。

 

 

“抖动”与工作集:

  抖动: 刚被换出的页很快又要被访问,需要将它重新调入。

  产生抖动的主要原因: 同时在系统中运行的进程太多,因此分配给每一个进程的物理块太少,导致频繁出现页面置换。

  进程的缺页率与进程所获得的物理块数有关。缺页率会随着物理块数的增加而减少,当物理块数达到某个数值后,对物理块数的增加不糊hi对缺页率有很好的改善。

  工作集:在某段时间间隔里,进程实际要访问页面的集合。

  预防抖动的方法:

    1)采取局部置换策略      只允许在分配给自己的内存空间内进行置换,不许获取其它进程的内存块

    2)

请求分段存储管理方式:

  在分段基础上所建立的请求分段式虚拟存储器系统,以分段为单位进行换入、换出。

  请求分段中的硬件支持:

    请求段表机制:增加了存取方式。  增补位。

  

 

 分段的共享和保护:

  共享段表:

  

  

 

posted @ 2020-08-07 13:46  你眼里的星辰  阅读(205)  评论(0)    收藏  举报