内存非连续分配管理方式

非连续分配容许一个程序分散地装入到不相邻的内存分区中,根据分区的大小是否固定分为分页存储管理方式和分段存储管理方式。程序员

基本分页存储管理方式

固定分区会产生内部碎片,动态分区会产生外部碎片,这两种技术对内存的利用率都比较低。咱们但愿内存的使用能尽可能避免碎片的产生,这就引入了分页的思想:把主存空间划分为大小相等且固定的块,块相对较小,做为主存的基本单位。每一个进程也以块为单位进行划分,进程在执行时,以块为单位逐个申请主存中的块空间。

分页的方法从形式上看,像分区相等的固定分区技术,分页管理不会产生外部碎片。但它又有本质的不一样点:块的大小相对分区要小不少,并且进程也按照块进行划分,进程运行时按块申请主存可用空间并执行。这样,进程只会在为最后一个不完整的块申请一个主存块空间时,才产生主存碎片,因此尽管会产生内部碎片,可是这种碎片相对于进程来讲也是很小的,每一个进程平均只产生半个块大小的内部碎片(也称页内碎片)。算法

1) 分页存储的几个基本概念

①页面和页面大小。进程中的块称为页(Page),内存中的块称为页框(Page Frame,或页帧)。外存也以一样的单位进行划分,直接称为块(Block)。进程在执行时须要申请主存空间,就是要为每一个页面分配主存中的可用页框,这就产生了页和页框的一一对应。

为方便地址转换,页面大小应是2的整数幂。同时页面大小应该适中,若是页面过小,会使进程的页面数过多,这样页表就过长,占用大量内存,并且也会增长硬件地址转换的开销,下降页面换入/换出的效率;页面过大又会使页内碎片增大,下降内存的利用率。因此页面的大小应该适中,考虑到耷间效率和时间效率的权衡。

②地址结构。分页存储管理的逻辑地址结构如图1所示。

编程


图1  分页存储管理的地址结构


地址结构包含两部分:前一部分为页号P,后一部分为页内偏移量W。地址长度为32 位,其中0~11位为页内地址,即每页大小为4KB;12~31位为页号,地址空间最多容许有220页。

③页表。为了便于在内存中找到进程的每一个页面所对应的物理块,系统为每一个进程创建一张页表,记录页面在内存中对应的物理块号,页表通常存放在内存中。

在配置了页表后,进程执行时,经过查找该表,便可找到每页在内存中的物理块号。可见,页表的做用是实现从页号到物理块号的地址映射,如图2所示。

缓存


图2  页表的做用

2) 基本地址变换机构

地址变换机构的任务是将逻辑地址转换为内存中物理地址,地址变换是借助于页表实现的。图3给出了分页存储管理系统中的地址变换机构。

性能


图3 分页存储管理的地址变换机构


在系统中一般设置一个页表寄存器(PTR),存放页表在内存的始址F和页表长度M。进程未执行时,页表的始址和长度存放在进程控制块中,当进程执行时,才将页表始址和长度存入页表寄存器。设页面大小为L,逻辑地址A到物理地址E的变换过程以下:操作系统

  1. 计算页号P(P=A/L)和页内偏移量W(W=A%L)。
  2. 比较页号P和页表长度M,若P >= M则产生越界中断,不然继续执行。
  3. 页表中页号P对应的页表项地址 = 页表起始地址F + 页号P * 页表项长度,取出该页表项内容b,即为物理块号。
  4. 计算E=b*L+W,用获得的物理地址E去访问内存。


以上整个地址变换过程均是由硬件自动完成的。

例如,若页面大小L为1K字节,页号2对应的物理块为b=8,计算逻辑地址A=2500 的物理地址E的过程以下:P=2500/1K=2,W=2500%1K=452,查找获得页号2对应的物理块的块号为 8,E=8*1024+452=8644。

下面讨论分页管理方式存在的两个主要问题:设计

  • 每次访存操做都须要进行逻辑地址到物理地址的转换,地址转换过程必须足够快,不然访存速度会下降;
  • 每一个进程引入了页表,用于存储映射机制,页表不能太大,不然内存利用率会下降。

3) 具备快表的地址变换机构

由上面介绍的地址变换过程可知,若页表所有放在内存中,则存取一个数据或一条指令至少要访问两次内存:一次是访问页表,肯定所存取的数据或指令的物理地址,第二次才根据该地址存取数据或指令。显然,这种方法比一般执行指令的速度慢了一半。

为此,在地址变换机构中增设了一个具备并行查找能力的高速缓冲存储器——快表,又称联想寄存器(TLB),用来存放当前访问的若干页表项,以加速地址变换的过程。与此对应,主存中的页表也常称为慢表,配有快表的地址变换机构如图4所示。

blog


图4  具备快表的地址变换机构


在具备快表的分页机制中,地址的变换过程:索引

  • CPU给出逻辑地址后,由硬件进行地址转换并将页号送入高速缓存寄存器,并将此页号与快表中的全部页号进行比较。
  • 若是找到匹配的页号,说明所要访问的页表项在快表中,则直接从中取出该页对应的页框号,与页内偏移量拼接造成物理地址。这样,存取数据仅一次访存即可实现。
  • 若是没有找到,则须要访问主存中的页表,在读出页表项后,应同时将其存入快表,以便后面可能的再次访问。但若快表已满,则必须按照必定的算法对旧的页表项进行替换。


注意:有些处理机设计为快表和慢表同时查找,若是在快表中查找成功则终止慢表的查找。

通常快表的命中率能够达到90%以上,这样,分页带来的速度损失就下降到10%如下。快表的有效性是基于著名的局部性原理。进程

4) 两级页表

第二个问题:因为引入了分页管理,进程在执行时不须要将全部页调入内存页框中,而只要将保存有映射关系的页表调入内存中便可。可是咱们仍然须要考虑页表的大小。以32 位逻辑地址空间、页面大小4KB、页表项大小4B为例,若要实现进程对所有逻辑地址空间的映射,则每一个进程须要220,约100万个页表项。也就是说,每一个进程仅页表这一项就须要4MB主存空间,这显然是不切实际的。而即使不考虑对所有逻辑地址空间进行映射的状况,一个逻辑地址空间稍大的进程,其页表大小也多是过大的。以一个40MB的进程为例,页表项共40KB,若是将全部页表项内容保存在内存中,那么须要10个内存页框来保存整个页表。整个进程大小约为1万个页面,而实际执行时只须要几十个页面进入内存页框就能够运行,但若是要求10个页面大小的页表必须所有进入内存,这相对实际执行时的几十个进程页面的大小来讲,确定是下降了内存利用率的;从另外一方面来讲,这10页的页表项也并不须要同时保存在内存中,由于大多数状况下,映射所须要的页表项都在页表的同一个页面中。

将页表映射的思想进一步延伸,就能够获得二级分页:将页表的10页空间也进行地址映射,创建上一级页表,用于存储页表的映射关系。这里对页表的10个页面进行映射只须要10个页表项,因此上一级页表只须要1页就足够(能够存储210=1024个页表项)。在进程执行时,只须要将这1页的上一级页表调入内存便可,进程的页表和进程自己的页面,能够在后面的执行中再i周入内存。

如图5所示,这是Intel处理器80x86系列的硬件分页的地址转换过程。在32位系统中,所有32位逻辑地址空间能够分为220(4GB/4KB)个页面。这些页面能够再进一步创建顶级页表,须要210个顶级页表项进行索引,这正好是一页的大小,因此创建二级页表便可。


图5  硬件分页地址转换


举例,32位系统中进程分页的工做过程:假定内核已经给一个正在运行的进程分配的逻辑地址空间是0x20000000到0x2003FFFF,这个空间由64个页面组成。在进程运行时,咱们不须要知道所有这些页的页框的物理地址,极可能其中不少页还不在主存中。这里咱们只注意在进程运行到某一页时,硬件是如何计算获得这一页的页框的物理地址便可。如今进程须要读逻辑地址0x20021406中的字节内容,这个逻辑地址按以下进行处理:
    逻辑地址: 0x20021406 (0010 0000 0000 0010 0001 0100 0000 0110 B)
    顶级页表字段:0x80 (00 1000 0000 B)
    二级页表字段:0x21 (00 0010 0001B)
    页内偏移量字段:0x406  (0100 0000 0110 B)

顶级页表字段的0x80用于选择顶级页表的第0x80表项,此表项指向和该进程的页相关的二级页表;二级页表字段0x21用于选择二级页表的第0x21表项,此表项指向包含所需页的页框;最后的页内偏移量字段0x406用于在目标页框中读取偏移量为0x406中的字节。

这是32位系统下比较实际的一个例子。看似较为复杂的例子,有助于比较深刻地理解,但愿读者能本身动手计算一遍转换过程。

创建多级页表的目的在于创建索引,这样不用浪费主存空间去存储无用的页表项,也不用盲目地顺序式查找页表项,而创建索引的要求是最高一级页表项不超过一页的大小。在 64位操做系统中,页表的划分则须要从新考虑,这是不少教材和辅导书中的常见题目,可是不少都给出了错误的分析,须要注意。

咱们假设仍然釆用4KB页面大小。偏移量字段12位,假设页表项大小为8B。这样,其上一级分页时,每一个页框只能存储29(4KB/8B)个页表项,而再也不是210个,因此上一级页表字段为9位。后面同理继续分页。64=12+9+9+9+9+9+7,因此需6级分页才能实现索引。不少书中仍然按4B页表项分析,虽然一样得出6级分页的结果,但显然是错误的。这里给出两个实际的64位操做系统的分页级别(注意:里面没有使用所有64位寻址,不过因为地址字节对齐的设计考虑,仍然使用8B大小的页表项),理解了表1中的分级方式,相信对多级分页就很是清楚了。

表1 两种系统的分级方式
平台 页面大小 寻址位数 分页级数 具体分级
Alpha 8KB 43 3 13+10+10+10
X86_64 4 KB 48 4 12+9+9+9+9

基本分段存储管理方式

分页管理方式是从计算机的角度考虑设计的,以提升内存的利用率,提高计算机的性能, 且分页经过硬件机制实现,对用户彻底透明;而分段管理方式的提出则是考虑了用户和程序员,以知足方便编程、信息保护和共享、动态增加及动态连接等多方面的须要。

1) 分段

段式管理方式按照用户进程中的天然段划分逻辑空间。例如,用户进程由主程序、两个子程序、栈和一段数据组成,因而能够把这个用户进程划分为5个段,每段从0开始编址,并分配一段连续的地址空间(段内要求连续,段间不要求连续,所以整个做业的地址空间是二维的)。其逻辑地址由段号S与段内偏移量W两部分组成。

在图6中,段号为16位,段内偏移量为16位,则一个做业最多可有216=65536个段,最大段长为64KB。


图6  分段系统中的逻辑地址结构


在页式系统中,逻辑地址的页号和页内偏移量对用户是透明的,但在段式系统中,段号和段内偏移量必须由用户显示提供,在髙级程序设计语言中,这个工做由编译程序完成。

2) 段表

每一个进程都有一张逻辑空间与内存空间映射的段表,其中每个段表项对应进程的一个段,段表项记录该段在内存中的起始地址和段的长度。段表的内容如图7所示。


图7  段表项


在配置了段表后,执行中的进程可经过查找段表,找到每一个段所对应的内存区。可见,段表用于实现从逻辑段到物理内存区的映射,如图8所示。


图8  利用段表实现地址映射

3) 地址变换机构

分段系统的地址变换过程如图9所示。为了实现进程从逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放段表始址F和段表长度M。其从逻辑地址A到物理地址E之间的地址变换过程以下:

  • 从逻辑地址A中取出前几位为段号S,后几位为段内偏移量W。
  • 比较段号S和段表长度M,若S多M,则产生越界中断,不然继续执行。
  • 段表中段号S对应的段表项地址 = 段表起始地址F + 段号S * 段表项长度,取出该段表项的前几位获得段长C。若段内偏移量>=C,则产生越界中断,不然继续执行。
  • 取出段表项中该段的起始地址b,计算 E = b + W,用获得的物理地址E去访问内存。


图9  分段系统的地址变换过程

4) 段的共享与保护。

在分段系统中,段的共享是经过两个做业的段表中相应表项指向被共享的段的同一个物理副原本实现的。当一个做业正从共享段中读取数据时,必须防止另外一个做业修改此共享段中的数据。不能修改的代码称为纯代码或可重入代码(它不属于临界资源),这样的代码和不能修改的数据是能够共享的,而可修改的代码和数据则不能共享。

与分页管理相似,分段管理的保护方法主要有两种:一种是存取控制保护,另外一种是地址越界保护。地址越界保护是利用段表寄存器中的段表长度与逻辑地址中的段号比较,若段号大于段表长度则产生越界中断;再利用段表项中的段长和逻辑地址中的段内位移进行比较,若段内位移大于段长,也会产生越界中断。

段页式管理方式

页式存储管理能有效地提升内存利用率,而分段存储管理能反映程序的逻辑结构并有利于段的共享。若是将这两种存储管理方法结合起来,就造成了段页式存储管理方式。

在段页式系统中,做业的地址空间首先被分红若干个逻辑段,每段都有本身的段号,而后再将每一段分红若干个大小固定的页。对内存空间的管理仍然和分页存储管理同样,将其分红若干个和页面大小相同的存储块,对内存的分配以存储块为单位,如图10所示。


图10  段页式管理方式


在段页式系统中,做业的逻辑地址分为三部分:段号、页号和页内偏移量,如图11 所示。


图11  段页式系统的逻辑地址结构


为了实现地址变换,系统为每一个进程创建一张段表,而每一个分段有一张页表。段表表项中至少包括段号、页表长度和页表起始地址,页表表项中至少包括页号和块号。此外,系统中还应有一个段表寄存器,指出做业的段表起始地址和段表长度。

注意:在一个进程中,段表只有一个,而页表可能有多个。

在进行地址变换时,首先经过段表查到页表起始地址,而后经过页表找到页帧号,最后造成物理地址。如图12所示,进行一次访问实际须要三次访问主存,这里一样可使用快表以加快查找速度,其关键字由段号、页号组成,值是对应的页帧号和保护码。

图12  段页式系统的地址变换机构
相关文章
相关标签/搜索