地址转译的相关问题(四)

各种页面错误及其处理

我们都知道,地址的转译需要如下的PTE 结构

地址转译的相关问题(四)_第1张图片

第一篇文章我们看到了正常的地址转译过程v 位总是为1,即PTE 有效,但是,虚拟地址到物理地址的转译并不总是这样的正常流程。当产生页面错误异常(14号),异常的陷阱处理器(_KiTrap0E函数)首先构造一个陷阱帧,然后把控制权交给内存管理器的MmAccessFault 函数。如果MmAccessFault 函数能能够解决此错误,则陷阱处理器正常返回;否则,_KiTrap0E 进行异常处理,具体的异常处理过程,暂不讨论。

 

NTSTATUS

MmAccessFault (

   IN ULONG_PTR FaultStatus,   // 发生错误时候的状态信息位

   IN PVOID VirtualAddress,        // 发生页面错误的虚拟地址

   IN KPROCESSOR_MODE PreviousMode, //此页面是发生在内核模式还是用户模式

   IN PVOID TrapInformation       // 页面错误陷阱帧的地址

)

 

 地址转译的相关问题(四)_第2张图片地址转译的相关问题(四)_第3张图片

 

上面我们可以看到MmAccessFault 函数的主要的工作流程,他的主要的功能就是进行各种检查,以及处理一些MiCopyOnWrite MiResolveDemandZeroFault 函数来解决页面错误。而其它需要解决的页面错误,绝大多数是调用了MiDispatchFault函数来完成的

 

NTSTATUS

MiDispatchFault (

    IN ULONG_PTR FaultStatus,                                                                                                 

   IN PVOID VirtualAddress,

   IN PMMPTE PointerPte,

   IN PMMPTE PointerProtoPte,

   IN LOGICAL RecheckAccess,

   IN PEPROCESS Process,

   IN PVOID TrapInformation,

   IN PMMVAD Vad

)

地址转译的相关问题(四)_第4张图片

页面换入I/O

当为了满足一个页面错误而必须发出一个读文件(页面文件或映射文件)操作时,页面换I/O就会发生。而且,因为页表本身也是可换页的,所以,在处理一个页面错误时,若系统还需要加载页表的页面(该页面包含了原始被引用页面所对应的PTE或者原型PTE),则可能会招致额外的页面错误。

页面换入I/O操作是同步的,也就是说,线程等待一个事件,直至I/O完成,异步过程调用(APC)的交付是不会中断这种操作的。换页器在I/O请求函数中使用一个特殊的修饰符来指明这是一个换页I/O。当换页I/O完成时,I/O系统触发一个事件,该事件唤醒换页器,以便让它继续处理页面换入过程。

当换页I/O操作正在进行时,导致页面错误的那个线程并不拥有任何关键的内存管理同步对象。在换页I/O发生的时候,该进程内的其他线程仍然可以使用虚拟内存的功能,以及处理页面错误

换页器I/O 完成时应该认识到的问题:

 

■同一个进程中或者不同进程中的另一个线程可以在个页面上产生页面错误(称为冲突 的页面错误,下一小节讲述这种情形);

■     页面己经被从虚拟地址空间中删掉(和重新映射)了

■     页面上的保护域己经改变了

■     页面错误可能是针对原型PTE的,并且映射此原型PTE的那个贞面可能己经不在工作集中了

换页器在换页I/O请求以前,在线程的内核栈中保存了足够的状态,以便来处理这些条件

因此,当换页I/O请求完成时,换贞器可以检测到这些条件,如果有必要的话,它可以不将页面变成有效的,而直接解除此页面错误。若导致页面错误的指令被再次激发,则换页器再次被调用,然后根据新的状态再来评估此PTE

 

冲突的页面错误

一个页面正在被换入,另一个线程或者进程也激发了该页面的页面错误,这种情形称为冲突的页面错误(collided page fault).

如果另一个线程或进程在同一个页面上出错,则换页器检测到冲突的页面错误,注意到该页面正在转移过程中in transition),以及一个读操作正在进行之中(PFN 数据库保留了这些信息,接下来将详细介绍),这种情况下,换页器发出一个等待操作,在该PFN数据库项中指定的事件上等待。此事件由第一个为了消除该页面错误而激发I/O请求的那个线程来初始化

 

I/O 操作完成时,所有在该事件上等待的线程都满足了等待的条件。第一个获得PFN数据库锁的线程负责执行页面换入完成操作,这些操作包括:检查I/O状态确保I/O操作已经完成,清除PFN数据库中的正在读取过程中位,以及更新PFN

 

随后的线程获取到PFN 数据库锁来清除冲突的页面错误时,换页器看到“正在读取过程中”位已经清除了,知道初始的更新已经执行过了。检查PFN 数据库项中的“页面换入错误(in-page error)标志,确保页面换入I/O 成功完成,如果”页面换入错误“标志已经被置上,该PTE 不被更新,且在导致页面错误的线程内引发一个页面换入错误异常。

 

下一篇讲授最后的几个函数,以及地址转译以及页面错误的整体描述和理解。

你可能感兴趣的:(基础知识)