os 分页存储管理方式

连续分配方式会形成许多“碎片”,虽然可通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻块的分区中,便可充分地利用内存空间,而无须再进行“紧凑”。基于这一思想而产生了离散分配方式。根据在离散分配时所分配地址空间的基本单位的不同,又可将离散分配分为以下三种

  • (1)分页存储管理方式。在该方式中,将用户程序的地址空间分为若干个固定大小的区域,称为“页”或“页面”。典型的页面大小为1KB。相应地,也将内存空间分为若干个物理块或页框( frame ),页和块的大小相同。这样可将用户程序的任一页放入任一物理块中,实现了离散分配。
  • (2)分段存储管理方式。这是为了满足用户要求而形成的一种存储管理方式。它把用户程序的地址空间分为若干个大小不同的段,每段可定义一组相对完整的信息。在存储器分配时,以段为单位,这些段在内存中可以不相邻接,所以也同样实现了离散分配。
  • (3)段页式存储管理方式。这是分页和分段两种存储管理方式相结合的产物。它同时具有两者的优点,是目前应用较广泛的一种存储管理方式。

分页存储管理的基本方法

1.页面和物理块
(1)页面

分页存储管理将进程的逻辑地址空间分成若干个页,并为各页加以编号,从0开始,如第0页、第1页等。相应地,也把内存的物理地址空间分成若干个块,同样也为它们加以编号,如0#块、1#块等等。在为进程分配内存时,以块为单位,将进程中的若干个页分别装入到多个可以不相邻接的物理块中。由于进程的最后一页经常装不满一块,而形成了不可利用的碎片,称之为“页内碎片”。

(2)页面大小

在分页系统中,若选择过小的页面大小,虽然一方面可以减小内存碎片,起到减少内存碎片总空间的作用,有利于内存利用率的提高,但另一方面却会造成每个进程占用较多的页面,从而导致进程的页表过长,占用大量内存。此外,还会降低页面换进换出的效率。然而,如果选择的页面过大,虽然可以减少页表的长度,提高页面换进换出的速度,但却又会使页内碎片增大。因此,页面的大小应选择适中,且页面大小应是2的幂,通常为1 KB ~8 KB .

2.地址结构

分页地址中的地址结构如下:
os 分页存储管理方式_第1张图片
它包含两部分内容:前一部分为页号 P ,后一部分为位(偏)移量 W ,即页内地址。图中的地址长度为32位,其中0-11位为页内地址,即每页的大小为4KB;12~31位为页号,地址空间最多允许有1M页
对某特定机器,其地址结构是一定的。若给定一个逻辑地址空间中的地址为 A ,页面的大小为 L ,则页号 P 和页内地址 d 可按下式求得:
os 分页存储管理方式_第2张图片
其中,INT是整除函数,MOD是取余函数。例如,其系统的页面大小为1KB,设A=2170B,则由上式可以求得P=2,d=122。

3.页表

在分页系统中,允许将进程的各个页离散地存储在内存的任一物理块中,为保证进程仍然能够正确地运行,即能在内存中找到每个页面所对应的物理块,系统又为每个进程建立了一张页面映像表,简称页表。在进程地址空间内的所有页(0~ n ),依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号,见下图的中间部分。在配置了页表后,进程执行时,通过査找该表,即可找到每页在内存中的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射
os 分页存储管理方式_第3张图片


地址变换机构

为了能将用户地址空间中的逻辑地址转换为内存空间中的物理地址,在系统中必须设置地址变换机构。该机构的基本任务是实现从逻辑地址到物理地址的转换。由于页内地址和物理地址是一一对应的(例如,对于页面大小是1KB的页内地址是0-1023,其相应的物理块内的地址也是0-1023,无需再进行转换),因此,地址变换机构的任务实际上只是将逻辑地址中的页号转换为内存中的物理块号。又因为页面映射表的作用就是用于实现从页号到物理块号的变换,因此,地址变换任务是借助于页表来完成的

1.基本的地址变换机构

进程在运行期间,需要对程序和数据的地址进行变换,即将用户地址空间中的逻辑地址变换为内存空间中的物理地址,由于它执行的频率非常高,每条指令的地址都需要进行变换,因此需要采用硬件来实现页表功能是由一组专门的寄存器来实现的一个页表项用一个寄存器。由于寄存器具有较高的访问速度,因而有利于提高地址变换的速度;但由于寄存器成本较高,且大多数现代计算机的页表又可能很大,使页表项的总数可达几千甚至几十万个,显然这些页表项不可能都用寄存器来实现。因此,页表大多驻留在内存中。在系统中只设置一个页表寄存器 PTR ( Page - Table Register ),在其中存放页表在内存的始址和页表的长度。平时,进程未执行时,页表的始址和页表长度存放在本进程的 PCB 中。当调度程序调度到某进程时,才将这两个数据装入页表寄存器中。因此,在单处理机环境下,虽然系统中可以运行多个进程,但只需一个页表寄存器。
当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址(相对地址)分为页号和页内地址两部分,再以页号为索引去检索页表。查找操作由硬件执行。在执行检索之前,先将页号与页表长度进行比较,如果页号大于或等于页表长度,则表示本次所访问的地址已超越进程的地址空间。于是,这一错误将被系统发现,并产生一地址越界中断。若未出现越界错误,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中。与此同时,再将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。这样便完成了从逻辑地址到物理地址的变换。下图示出了分页系统的地址变换机构。
os 分页存储管理方式_第4张图片

2.具有快表的地址变换机构

由于页表是存放在内存中的,这使 CPU 在每存取一个数据时,都要两次访问内存。第一次是访问内存中的页表,从中找到指定页的物理块号,再将块号与页内偏移量 W 拼接,以形成物理地址。第二次访问内存时,才是从第一次所得地址中获得所需数据(或向此地址中写入数据)。因此,采用这种方式将使计算机的处理速度降低近1/2。可见,以此高昂代价来换取存储器空间利用率的提高,是得不偿失的
为了提高地址变换速度,可在地址变换机构中增设一个具有并行查询能力的特殊高速缓冲寄存器,又称为“联想寄存器”( Associative Memory ),或称为“快表”,在 IBM 系统中又取名为 TLB ( Translation Look aside Buffer ),用以存放当前访问的那些页表项。此时的地址变换过程是:在 CPU 给出有效地址后,由地址变换机构自动地将页号 P 送入高速缓冲寄存器,并将此页号与高速缓存中的所有页号进行比较,若其中有与此相匹配的页号,便表示所要访问的页表项在快表中。于是,可直接从快表中读出该页所对应的物理块号,并送到物理地址寄存器中。如在快表中未找到对应的页表项,则还须再访问内存中的页表,找到后,把从页表项中读出的物理块号送往地址寄存器;同时,再将此页表项存入快表的一个寄存器单元中,亦即,重新修改快表。但如果联想寄存器已满,则 OS 必须找到一个老的且已被认为是不再需要的页表项,将它换出。下图示出了具有快表的地址变换机构。
os 分页存储管理方式_第5张图片
由于成本的关系,快表不可能做得很大,通常只存放16~512个页表项,这对中、小型作业来说,已有可能把全部页表项放在快表中;但对于大型作业而言,则只能将其一部分页表项放入其中。由于对程序和数据的访问往往带有局限性,因此,据统计,从快表中能找到所需页表项的概率可达90%以上。这样,由于增加了地址变换机构而造成的速度损失可减少到10%以下,达到了可接受的程度。


访问内存的有效时间

从进程发出指定逻辑地址的访问请求,经过地址变换,到在内存中找到对应的实际物理地址单元并取出数据,所需要花费的总时间,称为内存的有效访问时间( Effective Access Time , EAT )。假设访问一次内存的时间为 t ,在基本分页存储管理方式中,有效访问时间分为第一次访问内存时间(即查找页表对应的页表项所耗费的时间 t )与第二次访问内存时间(即将页表项中的物理块号与页内地址拼接成实际物理地址所耗费的时间 t )之和:

EAT=t+t=2t

在引入快表的分页存储管理方式中,通过快表查询,可以直接得到逻辑页所对应的物理块号,由此拼接形成实际物理地址,减少了一次内存访问,缩短了进程访问内存的有效时间。但是,由于快表的容量限制,不可能将一个进程的整个页表全部装入快表,所以在快表中查找到所需表项存在着命中率的问题。所谓命中率,是指使用快表并在其中成功查找到所需页面的表项的比率。这样,在引入快表的分页存储管理方式中,有效访问时间的计算公式即为

EAT=a x λ+(t+λ)(1-a)+t=2t+λ-t x a

上式中,λ表示查找快表所需要的时间, a 表示命中率, t 表示访问一次内存所需要的时间
可见,引入快表后的内存有效访问时间分为查找到逻辑页对应的页表项的平均时间 a x λ+(t+λ)(1-a),以及对应实际物理地址的内存访问时间 t 。假设对快表的访问时间λ为20ns(纳秒),对内存的访问时间 t 为100 ns ,则下表中列出了不同的命中率 a 与有效访问时间的关系:
os 分页存储管理方式_第6张图片
正是由于引入了快表,CPU访问数据所耗费的时间明显减少。


两级和多级页表

现代的大多数计算机系统都支持非常大的逻辑地址空间(232B~264B)。在这样的环境下,页表就变得非常大,要占用相当大的内存空间。例如,对于一个具有32位逻辑地址空间的分页系统,规定页面大小为4KB即212B ,则在每个进程页表中的页表项数可达1MB之多。又因为每个页表项占用一个字节,故每个进程仅仅其页表就要占用1MB的内存空间,而且还要求是连续的。显然这是不现实的,我们可以采用这样两个方法来解决这一问题:

  • 对于页表所需的内存空间,可采用离散分配方式,以解决难以找到一块连续的大内存空间的问题
  • 只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入
1.两级页表( Two - Level Page Table )

针对难于找到大的连续的内存空间来存放页表的问题,可利用将页表进行分页的方法,使每个页面的大小与内存物理块的大小相同,并为它们进行编号,即依次为0#页、1#页,…, n #页,然后离散地将各个页面分别存放在不同的物理块中。同样,也要为离散分配的页表再建立一张页表,称为外层页表( Outer Page Table ),在每个页表项中记录了页表页面的物理块号。下面我们仍以前面的32位逻辑地址空间为例来说明。当页面大小为4KB时(12位),若采用一级页表结构,应具有20位的页号,即页表项应有1M个;在采用两级页表结构时,再对页表进行分页,使每页中包含210(即1024)个页表项,最多允许有210个页表分页;或者说,外层页表中的外层页内地址 P2 为10位,外层页号 P1 也为10位。此时的逻辑地址结构如图所示。
os 分页存储管理方式_第7张图片
由图可以看出,在页表的每个表项中,存放的是进程的某页在内存中的物理块号,如0#页存放在1#物理块中,1#页存放在4#物理块中。而在外层页表的每个页表项中所存放的是某页表分页的首址,如0#页表存放在1011#物理块中。我们可以利用外层页表和页表这两级页表来实现进程从逻辑地址到内存中物理地址的变换。
为了方便实现地址变换,在地址变换机构中,同样需要增设一个外层页表寄存器,用于存放外层页表的始址,并利用逻辑地址中的外层页号作为外层页表的索引,从中找到指定页表分页的始址,再利用 P 作为指定页表分页的索引,找到指定的页表项,其中即含有该页在内存的物理块号,用该块号 P 和页内地址 d 即可构成访问的内存物理地址。下图示出了两级页表时的地址变换机构。
os 分页存储管理方式_第8张图片
上述对页表实施离散分配的方法,虽然解决了对于大页表无需大片连续存储空间的问题,但并未解决用较少的内存空间去存放大页表的问题。换言之,只用离散分配空间的办法并未减少页表所占用的内存空间。能够用较少的内存空间存放页表的唯一方法是,仅把当前需要的一批页表项调入内存,以后再根据需要陆续调入。在采用两级页表结构的情况下,对于正在运行的进程,必须将其外层页表调入内存,而对于页表则只需调入一页或几页。为了表征某页的页表是否已经调入内存,还应在外层页表项中增设一个状态位 s ,其值若为0,表示该页表分页不在内存中,否则说明其分页已调入内存。进程运行时,地址变换机构根据逻辑地址中的 P1 去查找外层页表;若所找到的页表项中的状态位为0,则产生一个中断信号,请求 OS 将该页表分页调入内存。

2.多级页表

对于32位的机器,采用两级页表结构是合适的,但对于64位的机器,采用两级页表是否仍然合适,须做以下简单分析。如果页面大小仍采用4 KB 即212 B ,那么还剩下52位,假定仍按物理块的大小(212位)来划分页表,则将余下的42位用于外层页号。此时在外层页表中可能有4096G个页表项,要占用16384 GB 的连续内存空间。这样的结果显然是不能令人接受的。因此,必须采用多级页表,将外层页表再进行分页,也就是将各分页离散地装入到不相邻接的物理块中再利用第2级的外层页表来映射它们之间的关系
对于64位的计算机,如果要求它能支持264(=1844744TB)规模的物理存储空间,则即使是采用三级页表结构也是难以办到的,而在当前的实际应用中也无此必要。故在近两年推出的64位 OS 中,把可直接寻址的存储器空间减少为45位长度(即245)左右,这样便可利用三级页表结构来实现分页存储管理。


反置页表(Inverted Page Table)

1.反置页表的引入

在分页系统中,为每个进程配置了一张页表,进程逻辑地址空间中的每一页,在页表中都对应有一个页表项。在现代计算机系统中,通常允许一个进程的逻辑地址空间非常大,因此就需要有许多的页表项,而因此也会占用大量的内存空间。为了减少页表占用的内存空间,引入了反置页表。一般页表的页表项是按页号进行排序的,页表项中的内容是物理块号。而反置页表则是为每一个物理块设置一个页表项,并将它们按物理块的编号排序,其中的内容则是页号和其所隶属进程的标识符。在 IBM 公司推出的许多系统中都来用了反置页表,如 AS /400、 IBM RISC System 和 IBM RT 等系统。

2.地址变换

在利用反置页表进行地址变换时,是根据进程标识符和页号,去检索反置页表。如果检索到与之匹配的页表项,则该页表项(中)的序号 i 便是该页所在的物理块号,可用该块号与页内地址一起构成物理地址送内存地址寄存器。若检索了整个反置页表仍未找到匹配的页表项,则表明此页尚未装入内存。对于不具有请求调页功能的存储器管理系统,此时则表示地址出错。对于具有请求调页功能的存储器管理系统,此时应产生请求调页中断,系统将把此页调入内存。
虽然反置页表可有效地减少页表占用的内存,例如,对于一个具有64MB的机器,如果页面大小为4KB,那么反置页表只占用64KB内存。然而在该表中只包含了已经调入内存的页面,并未包含尚未调入内存的页面。因此,还必须为每个进程建立一个外部页表( External Page Table )。该页表与传统的页表一样,当所访问的页面在内存时,并不需要访问外部页表,仅当发现所需之页面不在内存时,才使用它。在页表中包含了各个页在外存的物理位置,通过它可将所需之页面调入内存。
由于在反置页表中是为每一个物理块设置一个页表项,当内存容量很大时,页表项的数目还是会非常大的。要利用进程标识符和页号去检索这样大的一张线性表是相当费时的。于是可利用 Hash 算法来进行检索,这样可以很快地找到在反置页表中的相应页表项。不过在采用 Hash 算法时,可能会出现所谓的“地址冲突”,即有多个逻辑地址被映射到同一个 Hash 表项上,必须妥善解决这一问题。

你可能感兴趣的:(#,操作系统,os,分页存储管理方式)