windows内核源码详尽分析-线程同步篇_第1页
windows内核源码详尽分析-线程同步篇_第2页
windows内核源码详尽分析-线程同步篇_第3页
windows内核源码详尽分析-线程同步篇_第4页
windows内核源码详尽分析-线程同步篇_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

象、IO完成端口、可等待定时器、互斥、事件、信号量等,这些都是‘可等待’对象,可用于WaitForSingleObject等函数。StructKSEMAPHORE{DISPATCHER_HEADERHeader;//公共头LONGLimit;//最大信号量个数}Struct{…LONGSignalState;//信号状态量(>0表示有信号,<=0表示无信号)LIST_ENTRYWaitListHead;//等待块队列…}INBOOLEertable,//表示本次等待操作是否可被吵醒(即被强制唤醒)INPLARGE_INTEGERTimeOutOPTIONAL)//超时{PVOIDObject,KPROCESSOR_MODEPreviousMode=ExGetPreviousMode();LARGE_INTEGERSafeTimeOut;NTSTATUSif((TimeOut)&&(PreviousMode!={{SafeTimeOut=ProbeForReadLargeInteger(TimeOut);TimeOut=&SafeTimeOut;}{_SEH2_YIELD(return}}Status=if{WaitableObject=OBJECT_TO_OBJECT_HEADER(Object)->Type->DefaultObject;if(IsPointerOffset(WaitableObject))//ifDefaultObject是个偏移,不是指针{WaitableObject=(PVOID)((ULONG_PTR)Object+}{=}{Status=}}return}#defineIsPointerOffset(Ptr)((LONG)(Ptr)>=如果是个偏移值,那么DefaultObject值的最为0,否则为1。象记录在其对象类型的DefaultObject字段中。较大,函数也较长。重要的是对唤醒原因的理解。(把WaitStatus理解为唤醒原因就好了)NTSTATUS//返回值表示本次睡眠的唤醒原//注意下面的函数只能在DISPATCH_LEVEL以下调用,否则蓝屏。(除非Timeout!=NULL&&*Timeout==0)KeWaitForSingleObject(INPVOIDObject,//要等待的‘可直接等待对象’INKWAIT_REASONWaitReason,//线程上次被切出原INKPROCESSOR_MODEWaitMode,//表示这是来自用户模式/内核模式的等待请求INBOOLEertable,//表示本次等待操作是否可以被强制唤醒INPLARGE_INTEGERTimeoutOPTIONAL)//超时{PKTHREADThread=PKMUTANTCurrentObject(PKMUTANT)Object;//其实意思是(DISPATCHER_HEADER*)ObjectPKWAIT_BLOCKWaitBlock=&Thread->WaitBlock[0];PKWAIT_BLOCKTimerBlock&Thread->WaitBlock[TIMER_WAIT_BLOCK];PKTIMERTimer=&Thread->Timer;//复用这个超时定时器NTSTATUSWaitStatus;//其实表示‘上次唤醒原因’BOOLEANSwappable;//内核栈是否可换到外存LARGE_INTEGERDueTimeNewDueTimeInterruptTime;PLARGE_INTEGEROriginalDueTime=Timeout;ULONGHand=if(!Thread->WaitNext)gotoWaitStart;Thread->WaitNextFALSE;//复{=//fir是AP_EVLKiwpontxIntrlPfrq是AP_EECPCif((Thread->ApcState.KernelApcPending)&&!(Thread->SpecialApcDisable)&&(Thread->WaitIrql==PASSIVE_LEVEL)){}1、所等待的对象有信号了2、被强制唤醒{if(CurrentObject->Header.Type==MutantObject){if((CurrentObject->Header.SignalState>0)||(Thread==CurrentObject->OwnerThread)){if(CurrentObject->Header.SignalState!={KiSatisfyMutantWait(CurrentObjectThread);WaitStatus=Thread->WaitStatus;//唤醒原因gotoDontWait;//退出函数}Else异常}}//普通的等待对象只要DISPATCHER_HEADER头部中的SignalState0就表示有信号了elseif(CurrentObject->Header.SignalState>0){WaitStatus=STATUS_WAIT_0;//唤醒原因为‘真唤醒’gotoDontWait;退出函}WaitStatusKiCheckAlertability(Thread,AlertableWaitMode);ifWaitStatusSTATUS_WAIT_0)//if强制唤醒了,就break({InterruptTime.QuadPart=if((ULONGLONG)InterruptTime.QuadPart>=Timer-{WaitStatusSTATUS_TIMEOUT;//唤醒原因为‘超时’gotoDontWait;//退出函数}Timer->Header.Inserted=}if(Thread->Queue)KiActivateWaiterQueue(Thread->Queue);Thread->State=Waiting;//将线程标记为等待状态(即睡眠状态)if(Timeout)

=,1、临时唤醒。指被其他线程发来的内核APC临时唤醒,要求执行紧急APC任务强if(WaitStatusSTATUS_KERNEL_APC)//if唤醒原因不是临时唤醒,就退出函数了returnWaitStatus;(Timeout=}Thread->WaitIrqlKeRaiseIrqlToSynchLevel();}returnWaitStatus;}typedefstruct_KWAIT_BLOCK{struct_KTHREAD*Thread;//所属线程struct_KWAIT_BLOCK*NextWaitBlock;//下一个等待块(用来挂入线程的等待块链表)USHORTWaitKey;//本等待块是所属线程的第几个等待对象UCHARWaitType;//WaitAll/WaitAnyvolatileUCHARBlockState;}KWAIT_BLOCK,*PKWAIT_BLOCK,#defineThread->WaitBlockListWaitBlock;//等待块链表WaitBlock->WaitKey=0;//即等待块的索引WaitBlock->Object=Object;//要等待的目标对象Thread->WaitStatus=0;//复位唤醒原因if {}{}

KxSetTimerForThreadWait(Timer,*Timeout,&Hand);//设置好定时器对象DueTime.QuadPart=Timer->DueTime.QuadPart;TimerBlock->NextWaitBlock=WaitBlock;//单循环链表Timer->Header.WaitListHead.Flink=&TimerBlock->WaitListEntry;Timer->Header.WaitListHead.Blink=&TimerBlock-WaitBlock->NextWaitBlockWaitBlock;单循环链Thread->AlertableAlertable;//线程睡眠模式,是否可被提醒(即强制唤醒)Thread->WaitMode=WaitMode;//来自用户还是内核模式的等待请求Thread->WaitReasonWaitReason;上次线程切换原因Thread->WaitListEntry.Flink=NULL;SwappableKiCheckThreadStackSwap(Thread,WaitMode);//检测本线程的内核栈是否可以换到外存Thread->WaitTime=KeTickCount.Lort;//记录上次切出时间的函数KiCheckThreadStackSwap用来检测本线程的内核栈是否可以置换到外存BOOLEANKiCheckThreadStackSwap(INPKTHREADThread,INKPROCESSOR_MODE{if((WaitMode==UserMode)&&(Thread->EnableStackSwap)(Thread->Priority>=(LOW_REALTIME_PRIORITY+{}{

returnreturn}}KiCheckAlertability(INPKTHREADINBOOLEertable,//本次睡眠操作是否支持强制唤醒{{{Thread->Alerted[WaitMode]=FALSE;//复位}elseif((WaitMode!=KernelMode)&&{Thread->ApcState.UserApcPending=}elseif(Thread->Alerted[KernelMode]){Thread->Alerted[KernelMode]=}}elseif((WaitModeKernelMode&&(Thread-{;//}return}不支持强制唤醒,也会被其他线程发来的用户APC给强制搞醒。#defineKiAddThreadToWaitList(Thread,Swappable){if(Swappable)//为什么要满足这个条件,我也搞不清InsertTailList(&KeGetCurrentPrcb()->WaitListHead,&Thread->WaitListEntry);}VOIDINKPRIORITYIncrement)//唤醒线程后的优先级增量(以便尽快得到调度运行{PLIST_ENTRYWaitEntry,WaitList;PKWAIT_BLOCKWaitBlock;PKTHREADWaitThread;PKMUTANTFirstObject=ObjectPointer;NTSTATUSWaitStatus;WaitList=&FirstObject->Header.WaitListHead;WaitEntry=WaitList->Flink;while((FirstObject->Header.SignalState>0)&&(WaitEntry!={WaitBlock=CONTAINING_RECORD(WaitEntry,KWAIT_BLOCK,WaitListEntry);WaitThread=WaitBlock->Thread;WaitStatusSTATUS_KERNEL_APC;//模拟给那个等待者线程发送内核apc而临时唤醒它if(WaitBlock->WaitType==WaitAny)//WaitAnt类型的话,肯定满足分配了{WaitStatus=(NTSTATUS)WaitBlock->WaitKey;//唤醒原因改为‘真唤醒’,此处即索引}KiUnwaitThread(WaitThread,WaitStatus,Increment);//关键函数WaitEntry=WaitList->Flink;//下一个线程}}拟给它发送内核apc方式(其实没发送),临时唤醒它,进入下轮循环,继续测试它所等待的其他对象,#defineKiSatisfyObjectWait(Object,{if(Object)->Header.TypeMutantObject)互斥对象要特殊处{if((Object)->Header.SignalState==0)//if拥有计数==0{(Object)->OwnerThread=Thread->KernelApcDisable=Thread->KernelApcDisable-(Object)->ApcDisable;(({(Object)->AbandonedFALSE;//复=}}}elseif(((Object)->Header.Type&TIMER_OR_EVENT_TYPE)==EventSynchronizationObject)(Object)->Header.SignalState=0;elseif((Object)->Header.Type==}多只是要提醒一下,不管是什么同步对象,其的SignalState表示信号状态量计数,当该值<=0时表示01两种情况的‘特殊信号量’。VOIDKiUnwaitThread(INPKTHREADThread,//目INLONG_PTRWaitStatus,//唤醒原{,Thread->AdjustIncrementSCHAR)Increment;//上次优先级调整增量Thread->AdjustReason=AdjustUnwait;//调整原因}每当一个apc的时候,将调用下面的函数NTSTATUS{if(Thread!={if(ApcMode==KernelMode)//若要给其他线程一个内核{Thread->ApcState.KernelApcPending=TRUE;if(Thread->State==Running){RequestInterrupt=}elseif((Thread->State==Waiting)&&(Thread->WaitIrql==PASSIVE_LEVEL)!(Thread->SpecialApcDisable)&&(!(Apc->NormalRoutine)||{Status=,,}}elseif((Thread->State==Waiting)&&(Thread->WaitMode==UserMode)&&((Thread->Alertable)||(Thread->ApcState.UserApcPending))){Thread->ApcState.UserApcPending=TRUE;Status=STATUS_USER_APC;}}VOIDKiUnlinkThread(INPKTHREADThread,INNTSTATUS{PKTIMERTimer;Thread->WaitStatus|=WaitStatus;WaitBlock=Thread-{WaitBlock=WaitBlock->NextWaitBlock;}while(WaitBlock!=Thread-if(Thread->WaitListEntry.Flink)RemoveEntryList(&Thread-Timer=&Thread-if(Timer->Header.Inserted)KxRemoveTreeTimer(Timer);if(Thread->Queue)Thread->Queue->CurrentCount++;}LONGKiSwapThread(INPKTHREADCurrentThread,INPKPRCB{BOOLEANApcState=KIRQLWaitIrql;//上次切出时的irqlLONG_PTRWaitStatus;//上次唤醒原因PKTHREADNextThread;NextThreadPrcb->NextThread;//当前的抢占者线程if(NextThread){}{

Prcb->NextThread=Prcb->CurrentThread=NextThread;NextThread->State=Running;NextThreadKiSelectReadyThread(0Prcb);//调度处一个if(NextThread){}{}}

Prcb->CurrentThread=NextThread;NextThread->State=Running;InterlockedOr((PLONG)&KiIdleSummary,Prcb->SetMember);NextThread=Prcb->IdleThread;//使用空转线程Prcb->CurrentThread=NextThread;NextThread->State=Running;WaitIrqlCurrentThread->WaitIrql;//记录上次切出时的irqlApcState=KiSwapContext(CurrentThread,ifApcState)//切回来后,例行执行内核{KiDeliverApc(KernelMode,NULL,NULL);ASSERT(WaitIrql==PASSIVE_LEVEL);}WaitStatusCurrentThread->WaitStatus;//关键。返回该线程上次唤醒的原因returnWaitStatus;}INPVOIDObject[],//等待对INWAIT_TYPEWaitType,//WaitAll/AitAnyINKWAIT_REASONWaitReason,//上次切换原因INKPROCESSOR_MODEWaitMode,//来自用户模式/内核模式的等待请求INBOOLEertable,//本次等待是否可提醒(指是否可被强制唤醒)INPLARGE_INTEGERTimeoutOPTIONAL,//超时OUTPKWAIT_BLOCKWaitBlockArrayOPTIONAL)//等待块数{PKWAIT_BLOCKPKTHREADThread=PKWAIT_BLOCKTimerBlock&Thread->WaitBlock[TIMER_WAIT_BLOCK];//定时器等待块是固定的PKTIMERTimer=&Thread->Timer;NTSTATUSWaitStatus=BOOLEANPLARGE_INTEGEROriginalDueTime=Timeout;LARGE_INTEGERDueTime,NewDueTime,InterruptTime;ULONGIndex,Hand=0;WaitBlockArray=&Thread->WaitBlock[0];ifThread->WaitNextgotoWaitStart;//首轮循环从WaitStart处开始Thread->WaitNext=FALSE;for(;;){{{Thread->Preempted=if((Thread->ApcState.KernelApcPending)&&!(Thread->SpecialApcDisable)&&(Thread->WaitIrql<APC_LEVEL)){}{

Index=if(WaitType=={{CurrentObject=if(CurrentObject->Header.Type=={if((CurrentObject->Header.SignalState>0)||(Thread==CurrentObject->OwnerThread)){if(CurrentObject->Header.SignalState!={}{}}}

KiSatisfyMutantWait(CurrentObject,Thread);WaitStatus=Thread->WaitStatus|Index;gotoDontWait;//只要满足一个就退出函数elseif(CurrentObject->Header.SignalState>{WaitStatus=Index;}}while(Index<}Else{CurrentObject=if(CurrentObject->Header.Type=={if((Thread==CurrentObject->OwnerThread)&&(CurrentObject->Header.SignalState==(LONG)MINLONG)){}elseif((CurrentObject->Header.SignalState<=0)&&(Thread!=CurrentObject->OwnerThread)){}}elseif(CurrentObject->Header.SignalState<={//}}while(Index<if(IndexCount)//if所有对象都有信号{WaitBlock=WaitBlockArray;{CurrentObject=(PKMUTANT)WaitBlock->Object;KiSatisfyObjectWait(CurrentObject,Thread);WaitBlock=WaitBlock->NextWaitBlock;}while(WaitBlock!=WaitStatusThread->WaitStatus;//唤醒原因为‘真唤醒’类型gotoDontWait;}}WaitStatus=KiCheckAlertability(Thread,Alertable,WaitMode);if(WaitStatus!=STATUS_WAIT_0)break;if{InterruptTime.QuadPart=if((ULONGLONG)InterruptTime.QuadPart>=Timer-WaitStatus=STATUS_TIMEOUT;gotoDontWait;}Timer->Header.Inserted=TRUE;WaitBlock->NextWaitBlock=TimerBlock;}WaitBlock=WaitBlockArray;{CurrentObject=WaitBlock-WaitBlock=WaitBlock->NextWaitBlock;}while(WaitBlock!=if(Thread->Queue)KiActivateWaiterQueue(Thread->Queue);Thread->State=Waiting;KiAddThreadToWaitList(Thread,Swappable);if}

WaitStatus=KiSwapThread(Thread,唤醒原if(WaitStatus!=STATUS_KERNEL_APC)returnif(Timeout)Timeout=Thread->WaitIrql=KeRaiseIrqlToSynchLevel();}returnWaitStatus;return}#defineThread->WaitBlockList=WaitBlockArray;Index=0;{WaitBlock=&WaitBlockArray[Index];WaitBlock->Object=Object[Index];WaitBlock->WaitKey(USHORT)Index;//关键WaitBlock->WaitTypeWaitType;//所有等待块的等待类型都相同WaitBlock->Thread=Thread;WaitBlock->NextWaitBlock=&WaitBlockArray[Index+1];}while(Index<WaitBlock->NextWaitBlockWaitBlockArray;单循环链表Thread->WaitStatus=STATUS_WAIT_0;if{TimerBlock->NextWaitBlock=WaitBlockArray;KxSetTimerForThreadWait(Timer,*Timeout,&Hand);DueTime.QuadPart=Timer->DueTime.QuadPart;}Thread->AlertableAlertable;//是否可被强制唤Thread->WaitModeWaitMode;//来自用户模式/内核模式的等待请求Thread->WaitReason=WaitReason;//上次被切原因Thread->WaitListEntry.Flink=Swappable=KiCheckThreadStackSwap(Thread,typedefstructDISPATCHER_HEADERHeader;//公共头部LONGLimit;//信号量的最大信号个}KSEMAPHORE,NtCreateSemaphore(OUTPHANDLESemaphoreHandle,//返回信号量对象的句柄INACCESS_MASKDesiredAccess,INPOBJECT_ATTRIBUTESObjectAttributesOPTIONAL,//信号量的名称及其他属性INLONGInitialCount,//信号量的初始信号个数INLONGumCount)//支持的最大信号个{HANDLEKPROCESSOR_MODEPreviousMode=ExGetPreviousMode();NTSTATUSStatus;if(PreviousMode!={{}{_SEH2_YIELD(return}}if((umCount<=0)||(InitialCount<0)||(InitialCount>umCount))returnSTATUS_INVALID_PARAMETER;NULL,sizeof(KSEMAPHORE),0,0,(PVOID*)&Semaphore);if{ Status=ObInsertObject((PVOID)Semaphore,NULL,DesiredAccess,0,NULL,&hSemaphore);if(NT_SUCCESS(Status)){{*SemaphoreHandle=}{Status=}}}return}KeInitializeSemaphore(INPKSEMAPHORESemaphore,INLONGCount,INLONG{sizeof(KSEMAPHORE)/Semaphore->Limit=}#defineKeInitializeDispatcherHeader(Header,t,s, (Header)->Type= (Header)->Absolute= (Header)->Size= (Header)->Inserted= (Header)->SignalState=State;//初始信号个数 }当SignalState减到0时,就需要等待其他线程释放信号量。NtReleaseSemaphore(INHANDLEINLONGReleaseCount,//一次可以释放多个信号量,这将一次唤醒多个线程OUTPLONGPreviousCountOPTIONAL)//返回之前的信号个数{KPROCESSOR_MODEPreviousMode=ExGetPreviousMode();PKSEMAPHORESemaphore;NTSTATUSif((PreviousCount)&&(PreviousMode!={{}{_SEH2_YIELD(return}}if(ReleaseCount<=returnStatus=if{

{LONGPrevCount=if(PreviousCount)*PreviousCount=PrevCount;}{Status=}}return}KeReleaseSemaphore(INPKSEMAPHOREINKPRIORITYIncrement,//优先级增INBOOLEAN{LONGInitialState,State;KIRQLOldIrql;PKTHREADCurrentThread;OldIrql=InitialState=Semaphore->Header.SignalState;StateInitialStateAdjustment;//一次增加N个信号if((Semaphore->Limit<State)||Adjustment<0)){}Semaphore->Header.SignalState=if(!(InitialState)&&!(IsListEmpty(&Semaphore->Header.WaitListHead)))KiWaitTest(&Semaphore->Header,Increment);if(Wait==FALSE){}

CurrentThread=KeGetCurrentThread();CurrentThread->WaitNext=TRUE;CurrentThread->WaitIrql=OldIrql;return}用typedefstruct_KMUTANT{struct_KTHREAD*RESTRICTED_POINTEROwnerThread;//关键。当前拥有者线程BOOLEANAbandoned;//是否被拥有者线程因意外终止而抛弃了}KMUTANT,*PKMUTANT,KMUTEX,*PKMUTEX;KeInitializeMutant(INPKMUTANT{KIRQLOldIrql;if{}

CurrentThread=KeGetCurrentThread();Mutant->OwnerThreadCurrentThread;//看OldIrql=KiAcquireDispatcherLock();Mutant->OwnerThread=sizeof(KMUTANT)/InitialOwner01);//初始对外信号个数为0或者Mutant->Abandoned=Mutant->ApcDisable=}NtReleaseMutant(INHANDLEINPLONGPreviousCount{PKMUTANTKPROCESSOR_MODEPreviousMode=ExGetPreviousMode();NTSTATUSStatus;if((PreviousCount)&&(PreviousMode!={{}{_SEH2_YIELD(return}}Status=PreviousMode,if{{LONGPrev=KeReleaseMutant(Mutant,MUTANT_INCREMENT,FALSE,FALSE);if(PreviousCount)*PreviousCount=Prev;}{Status=}}return}KeReleaseMutant(INPKMUTANTINKPRIORITYINBOOLEANAbandon,//是否是因为线程意外终止而抛弃的INBOOLEANWait){KIRQLOldIrql;PKTHREADCurrentThread=KeGetCurrentThread();BOOLEANEnableApc=FALSE;OldIrql=PreviousStateMutant->Header.SignalState;//先前的拥有计数if(Abandon==FALSE)//最典型{if(Mutant->OwnerThread!={ExRaiseStatus(Mutant->Abandoned?STATUS_ABANDONED}}{}

Mutant->Header.SignalState1;//复位成1,表示直接对外有信号Mutant->Abandoned=TRUE;//标记为被拥有者线程意外抛弃了if(Mutant->Header.SignalState1)//如果该互斥对象变得对其他线程可用{ifPreviousState0)//若是正常释放的互斥对象(非意外终止原因{EnableApc=Mutant->ApcDisable;}Mutant->OwnerThreadNULL不再有拥有者线程了ifIsListEmpty(&Mutant-,}if(Wait==FALSE){}

CurrentThread->WaitNext=TRUE;CurrentThread->WaitIrql=OldIrql;if(EnableApc)KeLeaveCriticalRegion();returnPreviousState;}层的WaiFor操作就会一直阻塞,等待外层的WaitFor操作释放互斥对象,这样就会死锁。KeSetEvent(INPKEVENTINKPRIORITYIncrement,INBOOLEANWait){KIRQLOldIrql;PKTHREADThread;{return}OldIrql=KiAcquireDispatcherLock();PreviousState=Event->Header.SignalState;Event->Header.SignalState1;//置为有信号状(!(!({if(Event->Header.TypeEventNotificationObject)醒所有正在等待的线KxUnwaitThread(&Event->Header,Increment);KxUnwaitThreadForEvent(Event,}if{Thread=KeGetCurrentThread();Thread->WaitNext=TRUE;Thread->WaitIrql=OldIrql;}return}LONGKeResetEvent(INPKEVENT{KIRQLLONGPreviousState;OldIrql=KiAcquireDispatcherLock();PreviousState=Event->Header.SignalState;Event->Header.SignalState0;//复位成无信号状态return}#define*(OldIrql)= 义为unsignedint64。VOIDKeInitializeSpinLock(outPKSPIN_LOCKSpinLock{*SpinLock=}INPKSPIN_LOCKOUTPKIRQL);INPKSPIN_LOCKINKIRQL *(OldIrql)= 翻forceinlineKeAcquireSpinLockRaiseToDpc(inoutPKSPIN_LOCK{KIRQLOldIr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论