reactos操作系统实现(31)

 下面来分析保存数据时缺页中断函数,它的代码如下:

#001  NTSTATUS

#002  NTAPI

#003  MmpAccessFault(KPROCESSOR_MODE Mode,

#004                    ULONG_PTR Address,

#005                    BOOLEAN FromMdl)

#006  {

#007     PMM_AVL_TABLE AddressSpace;

#008     MEMORY_AREA* MemoryArea;

#009     NTSTATUS Status;

#010     BOOLEAN Locked = FromMdl;

#011 

 

调试输出。

#012     DPRINT("MmAccessFault(Mode %d, Address %x)/n", Mode, Address);

#013 

 

判断请求优先级是否大于DISPATCH_LEVEL级别,如果大于这个级别,就需要不能进行缺页处理。

#014     if (KeGetCurrentIrql() >= DISPATCH_LEVEL)

#015     {

#016        DPRINT1("Page fault at high IRQL was %d/n", KeGetCurrentIrql());

#017        return(STATUS_UNSUCCESSFUL);

#018     }

 

判断当前进程是否为空。

#019     if (PsGetCurrentProcess() == NULL)

#020     {

#021        DPRINT("No current process/n");

#022        return(STATUS_UNSUCCESSFUL);

#023     }

#024 

 

通过缺页中断的内存地址找到内存块。

#025     /*

#026      * Find the memory area for the faulting address

#027      */

#028     if (Address >= (ULONG_PTR)MmSystemRangeStart)

#029     {

 

如果是内存地址在系统范围内存里,就需要检查是否在内核模式下访问,否则在用户状态下访问是非法的。

#030        /*

#031         * Check permissions

#032         */

#033        if (Mode != KernelMode)

#034        {

#035           DPRINT1("MmAccessFault(Mode %d, Address %x)/n", Mode, Address);

#036           return(STATUS_ACCESS_VIOLATION);

#037        }

#038        AddressSpace = MmGetKernelAddressSpace();

#039     }

#040     else

#041     {

#042        AddressSpace = &PsGetCurrentProcess()->VadRoot;

#043     }

#044 

 

判断是否需要锁住内存。

#045     if (!FromMdl)

#046     {

#047        MmLockAddressSpace(AddressSpace);

#048     }

 

从所在内存空间里找到内存块。

#049     do

#050     {

#051        MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);

#052        if (MemoryArea == NULL || MemoryArea->DeleteInProgress)

#053        {

#054           if (!FromMdl)

#055           {

#056              MmUnlockAddressSpace(AddressSpace);

#057           }

 

这里返回非法访问的内存。

#058           return (STATUS_ACCESS_VIOLATION);

#059        }

#060 

#061        switch (MemoryArea->Type)

#062        {

 

系统内存非法访问。

#063           case MEMORY_AREA_SYSTEM:

#064              Status = STATUS_ACCESS_VIOLATION;

#065              break;

#066 

 

内存已经放分页缓存。

#067           case MEMORY_AREA_PAGED_POOL:

#068              Status = STATUS_SUCCESS;

#069              break;

#070 

 

这里就找到相应的内存块。

#071           case MEMORY_AREA_SECTION_VIEW:

#072              Status = MmAccessFaultSectionView(AddressSpace,

#073                                                MemoryArea,

#074                                                (PVOID)Address,

#075                                                Locked);

#076              break;

#077 

 

虚拟内存非法访问

#078           case MEMORY_AREA_VIRTUAL_MEMORY:

#079              Status = STATUS_ACCESS_VIOLATION;

#080              break;

#081 

 

共享内存非法访问。

#082           case MEMORY_AREA_SHARED_DATA:

#083              Status = STATUS_ACCESS_VIOLATION;

#084              break;

#085 

 

缺省都是返回非法访问内存。

#086           default:

#087              Status = STATUS_ACCESS_VIOLATION;

#088              break;

#089        }

#090     }

#091     while (Status == STATUS_MM_RESTART_OPERATION);

#092 

 

查找到内存块完成,并进行内存解锁操作。

#093     DPRINT("Completed page fault handling/n");

#094     if (!FromMdl)

#095     {

#096        MmUnlockAddressSpace(AddressSpace);

#097     }

#098     return(Status);

#099  }

上面这个函数,先判断缺页内存地址在系统空间,还是在用户空间,然后再在相应的空间里查找地址所有内存块。如果找到内存,就在函数MmAccessFaultSectionView里处理相应的功能。

你可能感兴趣的:(null,table,System,Access)