13.5.6 页面映射表(PMT)



13.5.6  页面映射表(PMT)

相对于每个区域的物理页面帧,页面映射表保存逻辑页面的相关信息。因此,可以有三个PMT:每一个用于进程的每个区域。因为区域被分成虚拟页面或逻辑页面0、1、2、…等等,只有对应物理页面帧才会提及到PMT。虚拟或逻辑页面号并不是显式的。例如,图13-30给出一个区域对应的PMT。为了便于读者更好地理解,图中才给出了虚拟页面号。

 
图13-30  区域的页面映射表(PMT)

在该图中,逻辑页面3可以驻留在物理页面帧19中,逻辑页面6可以驻留在物理页面帧83中。在地址转换时,内核要用到这个PMT。

编译器并不知道程序运行时将它的不同页面加载到物理内存中的位置。因此,在分页系统中,编译器生成的地址包括两部分内容,它们在该逻辑页面中分别是逻辑页面号(p)和逻辑页面内偏移量(d)。任何编译指令生成的地址就是(p+d),前面已经介绍过这部分内容。前面还介绍了虽然编译器只能生成一维虚拟地址,假定0是其开始地址,那么如果页面大小是2的整数次幂,就可以将同一个地址当作是二维地址p和d。

将程序加载到内存中的时候,内核查询空闲的页面帧列表,并将程序加载到该页面帧列表。此后,内核相应地更新PMT。在运行程序期间,地址转换单元(ATU)使用页面映射表针对每条指令查找到要转换的地址中逻辑页面对应的物理页面帧。偏移量d保持不变,因为页面大小和页面帧大小相同。获取物理页面帧号之后,将偏移量添加给它,不需要做任何改动,从而得到最终物理地址。因此,地址p+d就被转换成F+d,其中F是物理页面帧号。然后内核使用该地址取回/放置想要使用的数据/指令。

显然,对程序中的每个区域而言,都有一个PMT。如果区域是共享区(例如,编译器、编辑器或shell的文本区),那么对所有共享区域而言,区域中只有一个条目。因此,对这个共享的区域而言,它只有一个PMT。即使在每个进程区域(P区)表有多个这样的条目,情况也是这样:每个共享该区域的进程有一个条目。所有共享该区域的这些P区条目指向区域表条目,而该区域表条目又会指向PMT。

当进程死亡时,内核从进程表遍历到P区表,再遍历到区域表,然后是PMT,并删除该进程的所有区域链接。删除相应的P区条目,并将那些特定区域的区域引用计数减1。这之后,如果计数值为0,就可以释放该区域,因为没有进程再次使用该区域。如果情况如此,就释放区域表条目,并将其连接到空闲链表中。同时还要释放PMT,并将那些页面帧标注为"空闲"。现在将它们放回到空闲页面帧池,从而分配给新进程使用。完成这之后,删除该进程的P区表条目和进程表条目。同时,还要删除针对该进程维护的u区和内核堆栈。

如果内核以请求页面调度技术为内存管理方法,那么任何时候,并不是所有的页面都要在内存中。实际上,只将一部分页面从可执行文件加载到内存中。一段时间后,如果进程"请求"使用页面,就加载更多的页面。如果要删除某些页面,为相同或不同进程的某些不同的页面腾出空间,那么内核通常会用"最近未用过(LRU)"算法覆盖这些删除的页面。当要重写页面时,内核要确定是否将其回写到磁盘上加以保留。如果需要,内核预留出磁盘上的空间,这个空间被称作"交换文件",它用于交换页面。下面就是决策时要考虑的内容:

(1) 内核检查该页面帧的页面重写标志位。如果页面重写标志位等于1,表明该页面帧被修改过。因此,在其他页面覆盖该页面帧之前,需要将该页面帧写回到某个地方。内核将该页面写到交换文件中。

(2) 文本区中的页面被不可能重写过,因为当今的大多数编译器生成可重入程序,这个可重入程序不能修改自己。同样的,出于保护的原因,也不允许其他任何程序修改该程序。因此,不需要覆盖该页面。如果需要覆盖该页面,内核就从可执行文件中加载该页面。因为这是最初加载该页面的地方。

(3) 如果页面属于数据区或堆栈区,而且未修改过(也就是,页面重写标志位等于0),那么可以使用相同的逻辑。不需要覆盖该页面。只有当页面重写标志位等于1的时候,才需要将其覆盖到交换文件中。

 
图13-31  主存、可执行文件和交换文件

从进程出来的页面位于以下三个位置,如图13-31所示。

可执行文件

物理内存

交换文件

这会使得页面映射表复杂化,因为对每个虚拟页面而言,需要更多的信息对其定位和访问。页面映射表的形式如图13-32所示。

 
图13-32  请求页面中的PMT

区域表指向该区域的PMT。现在将PMT分成两部分:(a)页面表条目;(b)磁盘块条目。图13-33给出这两部分的具体内容。除了页面帧号之外,页面表条目还包括页面重写标志位(是否修改过)、寿命位(在内存中的时间)、引用位(用于实现LRU算法)、保护位和有效位字段。有效位说明了该页面是否在内存中,如果该有效位取值为1,该页面就有效。

 
图13-33  请求页面中的PMT

如果页面不在内存中,它表示存在缺页错误,那么就可以使用另一半PMT加载,也就是根据该页面的磁盘块条目定位该页面。这个条目指明该页面在磁盘上的位置(是可执行文件还是交换文件,以及其中的块号)。如果寻址得到的是无效页面,那么操作系统就会产生缺页错误,内核根据该信息将期望的页面从磁盘上加载到内存中。然后更新PMT,以反映这个新加载的页面。如果没有空的页面帧可以放置这个需要用的新页面,就可以使用LRU算法确定要覆盖的页面。为此用到了"引用"信息。页面表中的信息,也就是使用"页面重写标志位"确定在覆盖前是否要将该页面复制回到磁盘上。这样下一次,就可以加载页面这个更新过的最新副本。一旦将该页面复制回磁盘,就要更新该页面的磁盘块条目,这样下次出现缺页错误的时候就可以定位出该页面的磁盘块条目信息。

现在介绍UNIX内核创建和调度进程的必要步骤。这些步骤列举如下:

(1) 生成新的Pid。

(2) 在进程表中创建条目。此时,指针字段(指向P区表)是空的。

(3) 为该进程创建u区。

(4) 定位并读取内存中该进程想要执行的期望程序的可执行文件的头部。

(5) 定位该进程的不同区域,以及确定它们的大小和共享的可能性。

(6) 对非共享区而言,确定该区域所需的页面帧数。与用于分配所需内存的内存管理模块进行交互,并创建PMT(对相邻分配方案和请求页面而言,从复杂度来说单个分页方案的算法也会差异很大,因为这里将每个区域分成多个页面,在执行前要将所有这些页面全部加载到内存中)。

(7) 查看区域表中的空闲条目链表,为新(非共享的)区域分配新条目,并将其从空闲链表中删除。

(8) 按照以下内容,设置新分配区域表中的字段:

区域类型:由可执行文件获取

区域大小:由可执行文件获取

内存中的位置:PMT的地址

区域状态:"正加载"

访问计数:1

指向P区表的指针:空(截至目前)

(9) 与文件系统和I/O子系统交互,从而在步骤(6)中分配给这些区域的各自页面帧中真正的加载所需的页面。在全部加载完页面之后,区域表中的区域状态变成有效。

(10) 对于共享的区域而言,区域表中的条目已经存在了。访问该条目并递增"访问计数"字段。

(11) 不管区域是否共享,内核都要为进程的不同区域创建P区。此时,内核要正确设置所有的空指针。例如,内核可以从进程表中设置"指向P区表的指针"。如果使用双向指针,那么P区表条目也可以指向进程表。类似的,此时也可以对P区和P区表之间的双向指针进行适当的设置。将区域起始虚拟地址从可执行文件转移到P区表条目中。

(l2) 然后,内核可以计算进程的优先级,并根据优先级和状态(例如,准备就绪)将该进程的进程表条目链接到"其他内容"。以后,进程调度算法就可以使用这些链表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值