内存管理

2016-07-06  本文已影响150人  KevinCool

前段时间看了进程管理,觉得对编程简直大有裨益,至少对于多线程编程方面,对系统的进程管理有了非常深刻的理解,看来还是要多学习。今天开始学习内存管理这一节,看了一遍没怎么看懂,于是在这里写下笔记,慢慢咀嚼,直到看明白。

  1. 从源程序变成在内存中执行的程序
  1. 程序链接三种方式
  1. 程序装入的时候的三种方式
  1. 逻辑地址空间
    每个目标模块都是从0开始编址,称为目标模块的相对地址也称为逻辑地址,链接程序将依次将各个模块相对地址构成统一的从0开始编址的逻辑地址空间,不同进程可以有相同的逻辑地址,因为这些地址在装入内存的时候可以映射到主存的不同位置。

  2. 物理地址空间
    内存中物理单元的集合,地址转换的最终地址,进程在运行的时候指令和数据都要通过物理地址从主存中存取。地址重定位就是将逻辑地址转换成物理地址。

  3. 内存保护

  1. 覆盖
    将用户空间分成一个固定区和几个覆盖区,程序中经常活跃的部分放在固定区,其余部分,将要访问的段放入覆盖区,其它段放在外存中,在需要调用前,系统将其掉入覆盖区,替换覆盖区原有的段。不在覆盖区的段会常驻内存。

  2. 交换
    将处于等待状态的程序从内存移到辅存,换出。把准备好竞争CPU运行的程序从辅存移到内存,换入。内存管理器的交换过程速度足够快,总有进程在内存中可以执行。
    交换技术在不同进程或者作业中进行,覆盖用于同一个进程或者程序中。覆盖技术要求给出程序段之间的覆盖结构,对于主存无法存放用户程序的矛盾,是通过虚拟内存技术来解决的。

连续分配管理方式

给用户程序分配一个连续的内存空间。

这块将是非常关键而且重要的部分了,涉及了单一连续分配,固定区分配和动态分区分配。

  1. 单一连续分配
    内存分为系统区和用户区,因为只有一道程序,所以无需内存保护,无外部碎片,可以采用覆盖技术,只能用于单用户单任务的操作系统,有内部碎片,存储器利用率低。

  2. 固定分区分配
    将用户内存空间分为多个固定大小的区域,每个分区只装入一道作业,有空闲分区的时候再从外存的后备作业队列中,选择适当大小的作业装入该分区。

便于内存分配,将分区按照大小排队,建立一张分区说明表。回忆之。包含每个分区的起始地址,大小和状态。
两个问题,程序可能太大而放不进任何一个分区里,这时需要使用覆盖技术来使用内存空间。内部碎片,当程序小于固定分区大小的时候,也占用了一个完整的内存分区空间。

  1. 动态分区分配
    可变分区分配,动态划分内存的分区方法,根据进程的大小动态建立分区,使得分区大小正好适合进程的需要。系统中的分区大小和数目是可以变化的。
    在系统运行过程中,会产生较多的小的内存块,称为外部碎片。克服外部碎片可以通过紧凑技术解决,操作系统不时的对进程进行移动和整理,需要动态重定位寄存器的支持。
    动态分区的分配策略,是指将内存中的空闲块如何分配给进程使用:

首次适应算法会使得在内存的低地址处出现很多小的空闲分区(因为一般在内存低地址处分配空间),每次分配查找的时候,要经过这些分区,增加了查找的开销。
邻近适应算法会在内存的末尾分配空间,内存在前面使用后释放,不会参与分配,然后分裂成小碎片,通常比首次适应算法的结果要差。
最佳适应算法以容量递增的形式分配分区,会留下很小的难以利用的内存块,因此会产生最多的外部碎片。
最坏适应算法以容量递减的形式分配分区,会把最大的连续内存划分开,会很快导致没有可用的大的内存块。

内部碎片:存在于固定分区中,分区内部有空间浪费,称为内部碎片。
外部碎片:指在所有分区外的存储空间会变成越来越多的碎片,存在于动态分区分配中,各个进程将内存区域分配后,内存区域会残留的小的内存块。

非连续分配管理方式

允许一个程序分散的装入到不相邻的内存分区中,需要额外的空间去存储它们分散区域的索引,非连续分配方式的存储密度小于连续存储方式。

包括分页存储管理方式和分段存储管理方式,其中分页存储管理方式分为基本分页存储管理方式和请求分页存储管理方式。

  1. 基本分页存储管理方式
    把主存空间划分为大小相等而且固定的比较小的块,作为主存的基本单位,每个进程也以块为单位进行划分,进程在执行的时候,以块为单位逐个申请主存中的块空间。
    这样的分配方法不会产生外部碎片,进程只会为最后一个不完整的块申请一个主存块空间的时候,产生主存碎片,不过这个碎片相对于进程来讲也是非常小的,每个进程平均产生半个块大小的内部碎片,页内碎片。
    • 页面
      进程的块称之为页。
      内存中的块称之为页框,也称为页帧。
      外存中也以同样的单位进行划分,称为块。
      进程在执行时候需要申请主存空间,就是为每个页面分配主存中可用的页框,所以页和页框一一对应。
      页面大小就是说进程分成的基本单位页的大小,应该是2的整数幂。页面大小适中,太小会导致页面数过多,页表就太长,占用大量内存,增加硬件地址转换的开销,降低页面换入/换出效率。页面过大导致页内碎片增大,降低内存的利用率。
    • 地址结构
      前一部分为页号12-31位,所以地址空间最多有2^20页,后一部分是页内偏移量W,12位,0-11位,所以每页大小为4KB。地址结构决定了虚拟内存的寻址空间有多大。
      其实整个页面就是地址的集合,所以页面便移量也就确定了一定位置的物理地址。从而确定了从逻辑地址转换到物理地址的一个位置。
  1. 基本地址变换机构
    页表长度指的是一共有多少页M。
    页表项长度指的是每一页表项占多大的内存空间。
    页面大小是指每一页占多大的内存空间L。
    所以地址变换机构将逻辑地址转换成内存的物理地址的一般步骤如下:
  1. 具有快表的地址变换机构
    如果页表全部放在内存中,则存取一个数据或一条指令需要访问两次内存:第一次试访问页表,找到物理地址,然后通过物理地址存取数据和指令。
    在地址变换机构中增设了一个具有并行查找能力的高速缓冲存储器-快表,又称为联想寄存器TLB,用来存放当前访问的若干页表项,加速地址变换的过程,主存中页表称为慢表。
    具有快表的分页机制中,地址的变换过程:
  1. 两级页表

但是实际执行的时候只需要几十个页面进入内存页框就可以运行,但是如果要将10个页面的页表都放入内存,却只用几十个页面,不到一个页面的页表,这样就极大的降低了内存利用率。并且大部分情况下,映射需要的页表项都在页表的同一个页面中。
使用层次结构的页表:将页表的10页空间也进行地址映射,建立上一级页表,存储页表的映射关系,10个页面进行映射只需要10个页表项,而上一级页表仅仅需要1页就足够了,1页可以存储1024个页表项。
所以需要一张索引表来寻找对应的表,并且不用把所有的页表都调入内存,只有需要的时候才调入。构造一个页表的页表,就是二级页表。顶级页表最多只能由1个页面,也就是1024个页表项,对应1024个页面,占用的地址位数是10位,log2(1024)=10
所以对于一个32位的逻辑地址空间,32-10-12(页内偏移地址)=10位,所以二级页表大小也在一页之内。
所以假设第一级页表有10个页表项,则说明页表有10个页面,如果第一级页表有1024个页表项,说明页表有1024个页面,也就是32位逻辑空间最大的页表项了。然后第一级页表的页表项分别索引第二级页表,假设第一个页表项下的第二级页表,这就是说明索引了原来第一个页表页面的所有页表项。所以10个页面的页表恰好被整个二级页表索引完全。第一级页表大小在一页之内,第二级页表大小也在一页之内。
换一种说法就是第一级页表的页表项表示你想索引哪一个页面的页表,第二级页表的页表项就是表明你想索引的页面的页表的所有能索引到物理块的页表项都在这里了。

  1. 基本分段存储管理方式
    分段管理方式是考虑用户和程序员,以满足方便编程,信息保护和共享,动态增长及动态链接等多方面的需要。

段号和段内偏移一定要显示给出,因此分段管理的地址空间是二维的。

  1. 段页式管理方式
    作业的地址空间首先被分成了若干个逻辑段,每段都有自己的段号,然后将每一段分成若干个大小固定的页,对内存空间的管理和分页存储管理一样,将其分为若干个和页面大小相同的存储块,对内存的分配以存储块为单位。
上一篇 下一篇

猜你喜欢

热点阅读