reactos操作系统实现(29)
内存大小好像永远追不上人们的需求,以前以为512K就很大了,到现在内存已经是4G,8G内存了,但还是不能满足人们的需求。因为目前的系统都是多进程运行,每个进程都需要占用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文件里定义的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |