windows內(nèi)核源碼詳盡分析-中斷處理篇_第1頁
windows內(nèi)核源碼詳盡分析-中斷處理篇_第2頁
windows內(nèi)核源碼詳盡分析-中斷處理篇_第3頁
windows內(nèi)核源碼詳盡分析-中斷處理篇_第4頁
windows內(nèi)核源碼詳盡分析-中斷處理篇_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

中斷處(0x2A-0x2E5個系統(tǒng)預(yù)的中斷向量,0x2A:KiGetTickCount,0x2B:KiCallbaclReturn0x2C:KiRaiseAssertion,0x2D:KiDebugService,0x2E:KiSystemService)硬:最后的表項供驅(qū)動程序硬件中斷使用和自定義其他軟中斷使用(0x30-0xFF)linux等其他系統(tǒng)是怎么劃分這塊號段的,不管,我們只看Windows的情況為什么釣是在這段范圍內(nèi)搜索空白表項了(其實我們也完全可以從0x14開始搜索) IRQ2>8259A 一個IRQ,進(jìn)而,多個設(shè)備可以分配同一個中斷號。因此,一個中斷號可以共享給多個設(shè)備同時使用。IRP_MN_QUERY_RESOURCE_REQUIREMENTS,查詢得到初步的資源需求。然后,pnp管理器會找到相應(yīng)的硬件IRP_MN_FILTER_RESOURCE_REQUIREMENTS(功能驅(qū)動此時可以處理這個irp,修改資源需求),當(dāng)確定好最終的資源需求后,系統(tǒng)就協(xié)調(diào)分配端、中斷號、DIRQLIRP_MN_START_DEVICEIoConnectInterrupt(OUTPKINTERRUPT*InterruptObject,//返回創(chuàng)建的中斷對象(一般是一個數(shù)組)INPKSERVICE_ROUTINEServiceRoutine,//我們的isr(ourisr)INPVOIDServiceContext,//isrINPKSPIN_LOCKSpinLock,//我們isr的自旋鎖,用于多cpu互斥(一般傳NULL即可)INULONGVector,//分配到的中斷號INKIRQLIrql,//isr對應(yīng)的INKINTERRUPT_MODEInterruptMode,//表示是否允許執(zhí)行本中斷的下一個中斷INBOOLEANShareVector,//表示本中斷對象是否想要共享中斷號以及是否允許共享INKAFFINITYProcessorEnableMask,//本isr的cpu親緣性,一般全部cpu都親緣。INBOOLEANFloatingSave)//一般為FALSE{PKINTERRUPTPKINTERRUPTInterruptUsed;//當(dāng)前的中斷對象PKSPIN_LOCKSpinLockUsed;//實際使用的自旋鎖BOOLEANFirstRun;CCHARCount0;//cpu*InterruptObject=AffinityProcessorEnableMask&KeActiveProcessors;//本isr的cpu親緣性與實有cpu的交集while(Affinity){if(Affinity&1)Count++;Affinity>>=1;}if(!Count)returnSTATUS_INVALID_PARAMETER;IoInterrupt=ExAllocatePoolWithTag(NonPagedPool,(Count-1)*sizeof(KINTERRUPT)if(!IoInterrupt)return*InterruptObject=&IoInterrupt-SpinLockUsed=SpinLock?SpinLock:&IoInterrupt->SpinLock;Interrupt(PKINTERRUPT)(IoInterrupt1);//后面的中斷對象數(shù)組地址FirstRun=TRUE;RtlZeroMemory(IoInterrupt,sizeof(IO_INTERRUPT));Affinity=ProcessorEnableMask&KeActiveProcessors;for(Count0;Affinity;CountAffinity1)Count其實表示cpu{if(Affinity&{InterruptUsed=FirstRun?&IoInterrupt->FirstInterrupt:{//ififreturn}ifFirstRun=Else//記錄各cpu的那個中斷號上掛接的中斷對象地址}}return}如上,這個函數(shù)用來將指定isr掛接到各個cpu的指定中斷號上。因為在多cpu系統(tǒng)中,一個設(shè)備可以向每個cpu都發(fā)出中斷,因此,必須在每個cpu的IDT中都要掛接登記那個中斷的isr。具體是怎么掛接的呢?這個函數(shù)會創(chuàng)建一個中斷對象數(shù)組,然后將各個中斷對象對應(yīng)掛接到各cpu的同一中斷號上。由于老式機(jī)器是單cpu的,因此,早期的中斷對象結(jié)構(gòu)IO_INTERRUPT就包含一個中斷對象任意,后來的機(jī)器對其進(jìn)行了擴(kuò)展,在這個結(jié)構(gòu)后面是一個中斷對象數(shù)組,用來掛接到其他cpu上。typedefstruct{PKINTERRUPTInterrupt[UM_PROCESSORS];//記錄各cpu上掛接的中斷對象地址}IO_INTERRUPT,typedefstruct_KINTERRUPT{CSHORTCSHORTLIST_ENTRYInterruptListEntry;//用來掛入中斷對象鏈表PVOIDServiceContext;//isr參數(shù)ULONGTickCount;//沒用PKSPIN_LOCKActualLock;//我們isr實際使用的自旋鎖PKINTERRUPT_ROUTINEDispatchAddress;//中間的Dispatchisr函數(shù)地址CCHARNumber;//要掛往的目標(biāo)cpuKIRQLIrql;//isr對應(yīng)的isrBOOLEANFloatingSave;//一般為FALSEKINTERRUPT_MODEMode;//是否允許繼續(xù)執(zhí)行本中斷對象后面的中斷對象的isrULONGServiceCount;//沒用ULONGDispatchCode[DISPATCH_LENGTH];//這不是數(shù)組,而是一段代碼,表示本中斷對象的模板}KeInitializeInterrupt(INPKINTERRUPTINPKSERVICE_ROUTINEServiceRoutine,INPVOIDServiceContext,INPKSPIN_LOCKSpinLock,INULONGVector,INKIRQLIrql,INKIRQLSynchronizeIrql,INKINTERRUPT_MODEINBOOLEANShareVector,INCHARProcessorNumber,INBOOLEAN{ULONGPULONGDispatchCode&Interrupt->DispatchCode[0],PatchDispatchCode;//patch表示補(bǔ)丁處Interrupt->Type=InterruptObject;Interrupt->Size=if(SpinLock)//由于這個函數(shù)未導(dǎo)出,由系統(tǒng)內(nèi)部調(diào)用,傳的SpinLock參數(shù)很少為NULLInterrupt->ActualLockSpinLock;//使用頭部中公共的自旋鎖或者我們提供的自旋鎖{}

Interrupt->ActualLock=&Interrupt->SpinLock;Interrupt->ServiceRoutine=ServiceRoutine;Interrupt->ServiceContext=ServiceContext;Interrupt->Vector=Vector;Interrupt->Irql=Interrupt->SynchronizeIrql=SynchronizeIrql;Interrupt->Mode=InterruptMode;Interrupt->ShareVector=ShareVector;Interrupt->Number=ProcessorNumber;Interrupt->FloatingSave=FloatingSave;Interrupt->TickCount=MAXULONG;Interrupt->DispatchCount=MAXULONG;for(i0;iDISPATCH_LENGTH;*DispatchCode++=Patch=(PULONG)((ULONG)Patch+((ULONG)&KiInterruptTemplateObject-4-*PatchPtrToUlong(Interrupt);//也即將原movedx,0movedx,本中斷對象的地址Interrupt->Connected=FALSE;//尚未掛入}KiEnterTrapmovedx,0//這條指令的操作數(shù)0將態(tài)修改成具體中斷對象的地moveax,offset@KiInterruptTemplateHandler@8//KiInterruptTemplateHandler函數(shù)jmpeaxBOOLEAN//返回值表示是否掛接成功KeConnectInterrupt(INPKINTERRUPTInterrupt){BOOLEANConnected,Error,Status;KIRQLIrql,OldIrql;UCHARULONGDISPATCH_INFONumber=Interrupt->Number;//目標(biāo)cpuVectorInterrupt->Vector;//目標(biāo)中斷號Irql=Interrupt->Irql;SynchronizeIrqlif((Irql>HIGH_LEVEL)||(Number>=KeNumberProcessors)||(Interrupt->SynchronizeIrql<Irql)||(Interrupt->FloatingSave)){return}Connected=Error=KeSetSystemAffinityThread(1Number);//改變當(dāng)前線程的cpu親緣性先,挪到目標(biāo)cpuOldIrql=KiAcquireDispatcherLock();if(!Interrupt->Connected)//if尚未掛接{KiGetVectorDispatch(Vector,&Dispatch);if(Dispatch.TypeNoConnect{Interrupt->Connected=Connected=TRUE;KiConnectVectorToInterrupt(Interrupt,StatusHalEnableSystemInterrupt(Vector,Irql,Interrupt->Mode);//APIC相關(guān)if(!Status)Error=TRUE;}elseif((Dispatch.Type!=UnknownConnect)&&//已掛接有中斷對象(Interrupt->ShareVector)&& (Dispatch.Interrupt->ShareVector)&&(Dispatch.Interrupt->Mode==Interrupt->Mode)){Interrupt->Connected=Connected=if(Dispatch.Type!={ASSERT(Dispatch.Interrupt->Mode!=Latched);}}}if((Connected)&&(Error)){Connected=}return}VOIDKiGetVectorDispatch(INULONGVector,INPDISPATCH_INFO{PKINTERRUPT_ROUTINEPVOIDUCHARUCHAREntryHalVectorToIDTEntry(Vector);//這個宏將中斷向量號轉(zhuǎn)換為IDT表項索引(一般相同Dispatch->NoDispatch=(PVOID)(((ULONG_PTR)&KiStartUnexpectedRange)(Entry–0x30)*KiUnexpectedEntrySize);Dispatch->FloatingDispatch=NULL;//尚不支持Dispatch->FlatDispatch=NULL;CurrentKeQueryInterruptHandler(Vector);//獲得這個中斷向量處當(dāng)前存放的isrif((PKINTERRUPT_ROUTINE)Current==Dispatch-{}{

Dispatch->InterruptNULL;//表示尚未掛接有任何中斷對象Dispatch->Interrupt=CONTAINING_RECORD(Current,KINTERRUPT,DispatchCode);Handler=Dispatch->Interrupt->DispatchAddress;if(Handler==Dispatch-Dispatch->Type=ChainConnect;//上次的中斷對象是以方式掛上去elseif((Handler==Dispatch->InterruptDispatch)||(Handler==Dispatch->FloatingDispatch)){}

==}}是個用戶自定義的isr,也可能沒有isr(即以KiUnexpectedInterruptN函數(shù)占位)。KeQueryInterruptHandler(INULONG{PKIPCRPcr=UCHAREntry=return(PVOID)(((Pcr->IDT[Entry].ExtendedOffset<<16)&0xFFFF0000)|(Pcr->IDT[Entry].Offset&0xFFFF));}VOIDKiConnectVectorToInterrupt(INPKINTERRUPTInterrupt,INCONNECT_TYPEType{DISPATCH_INFOKiGetVectorDispatch(Interrupt->Vector,&Dispatch);if(TypeNoConnect)//if用戶要撤銷掛接Handler=Dispatch.NoDispatch;{//填好本中斷對象的dispatchInterrupt->DispatchAddress=(Type==NormalConnect)?Handler=(PVOID)&Interrupt->DispatchCode;//本中斷對象的模板isr}KeRegisterInterruptHandler(Interrupt->Vector,Handler);}VOIDKeRegisterInterruptHandler(INULONGVector,INPVOID{UCHARULONG_PTRPKIPCRPcr=Entry=Address=Pcr->IDT[Entry].ExtendedOffset=(USHORT)(Address>>16);Pcr->IDT[Entry].Offset=(USHORT)Address;}的,那么這些中斷對象將組成一個鏈表。這樣,當(dāng)cpuIDTVOIDKiInterruptTemplateHandler(INPKTRAP_FRAMETrapFrame,INPKINTERRUPTInterrupt){,}isr都是KiChainedDispatch,反之則是KiInterruptDispatch。我們看:VOIDKiChainedDispatch(INPKTRAP_FRAMETrapFrame,INPKINTERRUPT{KIRQLBOOLEANPLIST_ENTRYNextEntry,ListHead;({ListHead=&Interrupt->InterruptListEntry;NextEntry=ListHead;{if(Interrupt->SynchronizeIrqlInterrupt->Irql)//再次提升irqlOldIrql=KfRaiseIrql(Interrupt->SynchronizeIrql);Handled=Interrupt->ServiceRoutine(Interrupt,Interrupt->ServiceContext);if(Interrupt->SynchronizeIrql>Interrupt->Irql)if((Handled)&&(Interrupt->Mode==LevelSensitive))break;NextEntry=NextEntry->Flink;if(NextEntryListHead)//if{if(Interrupt->Mode==LevelSensitive)if(!Handled)break;//if}Interrupt=CONTAINING_RECORD(NextEntry,KINTERRUPT,}KiExitInterrupt(TrapFrame,OldIrql,}Else//清理中斷Trap幀,恢復(fù)中斷現(xiàn)場,回到原斷點處繼續(xù)執(zhí)行KiExitInterrupt(TrapFrame,OldIrql,TRUE);}BOOLEANInterruptService(instruct_KINTERRUPT*Interrupt,inPVOIDServiceContexTRUE。否則應(yīng)返回FALSE,讓系統(tǒng)繼續(xù)尋找中斷對象鏈表中的下一個中斷對象去認(rèn)領(lǐng)。VOIDFASTCALLKiInterruptDispatch(INPKTRAP_FRAMETrapFrame,INPKINTERRUPT{KIRQL{}}

KiExitInterrupt(TrapFrame,OldIrql,FALSE);KiExitInterrupt(TrapFrame,OldIrql,r后,就返回了,不會有在鏈表中查找的過程。VOIDIoDisconnectInterrupt(PKINTERRUPT{LONGIoInterruptCONTAINING_RECORD(InterruptObject,IO_INTERRUPT,FirstInterrupt);for(i=0;i<KeNumberProcessors;i++)//撤銷其它中斷對象的掛接{if(IoInterrupt->Interrupt[i])}}BOOLEANKeDisconnectInterrupt(INPKINTERRUPT{KIRQLOldIrql,Irql;ULONGVector;DISPATCH_INFODispatch;BOOLEANState;KeSetSystemAffinityThread(1<<Interrupt->Number);OldIrql=KiAcquireDispatcherLock();State=Interrupt->Connected;if(State){Irql=Interrupt->Irql;Vector=Interrupt->Vector;if(Dispatch.Type==ChainConnect){ASSERT(Irql<=if(InterruptDispatch.Interrupt)//if{Dispatch.Interrupt=CONTAINING_RECORD(Dispatch.Interrupt->}NextInterrupt=CONTAINING_RECORD(Dispatch.Interrupt-if(Dispatch.InterruptNextInterrupt)//也即if{,}}//{HalDisableSystemInterrupt(Interrupt->Vector,Irql);}Interrupt->Connected=}returnState;}三層。第一層是中斷對象的模板isr,第二層是中斷對象的dispatchisr,第三層才是用戶自己提供的isrisr。因此,也可以說,我們提供的那個isrIDTisrisr。當(dāng)然,程序員,也可以IDT中的表項,改成自己的isr,這就是所謂的isrhook(注意要進(jìn)行isrhook的話,必須每個cpu都要hook)最后我們看一下典型的系統(tǒng)時鐘中斷是怎么處理的。系統(tǒng)每隔10ms產(chǎn)生一次時鐘中斷,時鐘中斷的IRQ固定是0,中斷號默認(rèn)映射到0x30,時鐘中斷的isr最終進(jìn)入下面的函數(shù)。VOIDHalpClockInterruptHandler(INPKTRAP_FRAME{KIRQLIrql;ifHalBeginSystemInterrupt(CLOCK2_LEVEL,0x30,&Irql))//0x30{/*Updatetheperformancecounter*/HalpPerfCounter.QuadPart+=HalpCurrentRollOver;HalpPerfCounterCutoff=KiEnableTimerWatchdog;}}VOIDKeUpdateSystemTime(INPKTRAP_FRAMETrapFrame,INULONGIncrement,INKIRQL{PKPRCBPrcb=KeGetCurrentPrcb();ULARGE_INTEGERCurrentTime,InterruptTime;ULONGHand,OldTickCount;InterruptTime.HighPartSharedUserData->InterruptTime.High1Time;InterruptTime.Lort=SharedUserData->InterruptTime.Lort;InterruptTime.QuadPart+=Increment;//Increment一般為10msSharedUserData->InterruptTime.High1TimeInterruptTime.HighPart;SharedUserData->InterruptTime.Lort=InterruptTime.Lort;SharedUserData->InterruptTime.High2TimeInterruptTime.HighPart;OldTickCount=KeTickCount.Lort;/*Checkfor pletetick*/if(KiTickOffset<=0){CurrentTime.HighPart=SharedUserData->SystemTime.High1Time;CurrentTime.Lort=SharedUserData->SystemTime.Lort;CurrentTime.QuadPart+=KeTimeAdjustment;SharedUserDa

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論