zl程序教程

您现在的位置是:首页 >  系统

当前栏目

reactos操作系统实现(29)

操作系统 实现 29 reactos
2023-09-14 09:10:38 时间

 内存大小好像永远追不上人们的需求,以前以为512K就很大了,到现在内存已经是4G8G内存了,但还是不能满足人们的需求。因为目前的系统都是多进程运行,每个进程都需要占用4G的内存,那么10个进程,就占用相当可观的内存了。这时就需要把进程不经常使用的内存数据切换到硬盘里,需要时再换回来。如果一个进程的内存已经换到硬盘上,而这个进程又想访问那些在硬盘的内存数据时,就会产生一个缺页中断。这个中断是CPU产生的,并且进入操作系统的中断门处理函数里,那么ReactOS是怎么样处理的呢?其实它是调用下面的函数来处理这个中断的,如下:

#001  .func KiTrap14

#002  TRAP_FIXUPS kite_a, kite_t, DoFixupV86, DoNotFixupAbios

#003  _KiTrap14:

#004 

 

中断入口寄存器保存。

#005      /* Enter trap */

#006      TRAP_PROLOG kite_a, kite_t

#007 

 

检查是否有VDM标志。

#008      /* Check if we have a VDM alert */

#009      cmp dword ptr PCR[KPCR_VDM_ALERT], 0

#010      jnz VdmAlertGpf

#011 

 

获取当前线程。

#012      /* Get the current thread */

#013      mov edi, PCR[KPCR_CURRENT_THREAD]

#014 

 

获取当前帧指针。

#015      /* Get the stack address of the frame */

#016      lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]

#017      sub eax, [edi+KTHREAD_INITIAL_STACK]

#018      jz NoFixUp

#019 

#020      /* This isn't the base frame, check if it's the second */

#021      cmp eax, -KTRAP_FRAME_EFLAGS

#022      jb NoFixUp

#023 

#024      /* Check if we have a TEB */

#025      mov eax, PCR[KPCR_TEB]

#026      or eax, eax

#027      jle NoFixUp

#028 

#029      /* Fixup the frame */

#030      call _KiFixupFrame

#031 

#032      /* Save CR2 */

#033  NoFixUp:

#034      mov edi, cr2

#035 

#036      /* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */

#037      test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK

#038      je HandlePf

#039 

#040      /* Enable interrupts and check if we got here with interrupts disabled */

#041      sti

#042      test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK

#043      jz IllegalState

#044 

#045  HandlePf:

#046      /* Send trap frame and check if this is kernel-mode or usermode */

#047      push ebp

#048      mov eax, [ebp+KTRAP_FRAME_CS]

#049      and eax, MODE_MASK

#050      push eax

#051 

 

设置好参数,准备调用函数MmAccessFault来处理缺页错误。

#052      /* Send faulting address and check if this is read or write */

#053      push edi

#054      mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]

#055      and eax, 1

#056      push eax

#057 

#058      /* Call the access fault handler */

#059      call _MmAccessFault@16

#060      test eax, eax

#061      jl AccessFail

#062 

 

已经成功处理了缺页中断,返回调用中断处理。

#063      /* Access fault handled, return to caller */

#064      jmp _Kei386EoiHelper@0

#065 

#066  AccessFail:

#067      /* First check if this is a fault in the S-LIST functions */

#068      mov ecx, offset _ExpInterlockedPopEntrySListFault@0

#069      cmp [ebp+KTRAP_FRAME_EIP], ecx

#070      jz SlistFault

#071 

#072      /* Check if this is a fault in the syscall handler */

#073      mov ecx, offset CopyParams

#074      cmp [ebp+KTRAP_FRAME_EIP], ecx

#075      jz SysCallCopyFault

#076      mov ecx, offset ReadBatch

#077      cmp [ebp+KTRAP_FRAME_EIP], ecx

#078      jnz CheckVdmPf

#079 

#080      /* FIXME: TODO */

#081      UNHANDLED_PATH

#082      jmp _Kei386EoiHelper@0

#083 

#084  SysCallCopyFault:

#085      /* FIXME: TODO */

#086      UNHANDLED_PATH

#087      jmp _Kei386EoiHelper@0

#088 

#089      /* Check if the fault occured in a V86 mode */

#090  CheckVdmPf:

#091      mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]

#092      shr ecx, 1

#093      and ecx, 1

#094      test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK

#095      jnz VdmPF

#096 

#097      /* Check if the fault occured in a VDM */

#098      mov esi, PCR[KPCR_CURRENT_THREAD]

#099      mov esi, [esi+KTHREAD_APCSTATE_PROCESS]

#100      cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0

#101      jz CheckStatus

#102 

#103      /* Check if we this was in kernel-mode */

#104      test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK

#105      jz CheckStatus

#106      cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK

#107      jz CheckStatus

#108 

#109  VdmPF:

#110      /* FIXME: TODO */

#111      UNHANDLED_PATH

#112 

#113      /* Save EIP and check what kind of status failure we got */

#114  CheckStatus:

#115      mov esi, [ebp+KTRAP_FRAME_EIP]

#116      cmp eax, STATUS_ACCESS_VIOLATION

#117      je AccessViol

#118      cmp eax, STATUS_GUARD_PAGE_VIOLATION

#119      je SpecialCode

#120      cmp eax, STATUS_STACK_OVERFLOW

#121      je SpecialCode

#122 

#123      /* Setup an in-page exception to dispatch */

#124      mov edx, ecx

#125      mov ebx, esi

#126      mov esi, edi

#127      mov ecx, 3

#128      mov edi, eax

#129      mov eax, STATUS_IN_PAGE_ERROR

#130      call _CommonDispatchException

#131 

#132  AccessViol:

#133      /* Use more proper status code */

#134      mov eax, KI_EXCEPTION_ACCESS_VIOLATION

#135 

#136  SpecialCode:

#137      /* Setup a normal page fault exception */

#138      mov ebx, esi

#139      mov edx, ecx

#140      mov esi, edi

#141      jmp _DispatchTwoParam

#142 

#143  SlistFault:

#144      /* FIXME: TODO */

#145      UNHANDLED_PATH

#146 

#147  IllegalState:

#148 

#149      /* This is completely illegal, bugcheck the system */

#150      push ebp

#151      push esi

#152      push ecx

#153      push eax

#154      push edi

#155      push IRQL_NOT_LESS_OR_EQUAL

#156      call _KeBugCheckWithTf@24

#157 

#158  VdmAlertGpf:

#159 

#160      /* FIXME: NOT SUPPORTED */

#161      UNHANDLED_PATH

#162  .endfunc

 

通过上面函数的分析,可以看到主要调用函数MmAccessFault来处理缺页中断,这个函数在ntoskrnl/mm/mm.c文件里定义的。