4.WaitForSingleObject函数分析
無論可等待對象是何種類型,線程都是通過:
WaitForSingleObject
WaitForMultipleObjects
進入等待狀態的,這兩個函數是理解線程等待與喚醒進制的核心
WaitForSingleObject參數說明
WaitForSingleObject對應的內核函數:
NTSTATUS stdcall NtWaitForSingleObject ( HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout )Handle 用戶層傳遞的等待對象的句柄 (具體細節參加句柄表專題)
Alertable 對應 KTHREAD 結構體的 Alertable 屬性如果為1在插入用戶APC時,該線程將被吵醒
Timeout 超時時間
NtWaitForSingleObject
KeWaitForSingleObject:上半部分
!process 89316020 dt _KTHREAD 892db020 dt _KWAIT_BLOCK 892db020+70每個等待塊大小為0x18。
如果等待3個對象的話它就會占用前3個等待塊,最后一個是給定時器用的。
如果你有4個等待對象它就不會用這個位置了,它會一次性分配新的空間。
KeWaitForSingleObject的關鍵循環
while(true)//每次線程被其他線程喚醒,都要進入這個循環{if(符合激活條件)//1超時 2等待對象SignalState > 0{//1修改SignalState //2退出循環}else//SignalState不大于0 也沒超時{if(第一次執行){//將當前線程的等待塊掛到等待對象的鏈表 (WaitListHead) 中;//將自己掛入等待隊列(KiaitListHead)//切換線程...再次獲得CPU時,從這里開始執行}}} 1)線程將自己+5c位置清0 2)釋放_KWAIT_BLOCK所占內存WaitForSingleObject參數說明
kd> dt _DISPATCHER_HEADER nt!_DISPATCHER_HEADER+0x000 Type //該對象類型+0x001 Absolute +0x002 Size +0x003 Inserted+0x004 SignalState //該分發器信號狀態 (值大于0就是有信號 分發器對象也稱為同步對象)+0x008 WaitListHead //雙向鏈表頭,鏈著所有等待塊(此鏈表包含了所有正在等待該分發器對象的線程)不同的等待對象,用不同的方法來修改_DISPATCHER_HEADER(SignalState)比如:如果可等待對象是EVENT,其他線程通常使用SetEvent來設置SignalState= 1并且,將正在等待該對象的其他線程喚醒,也就是從等待鏈表(KiWaitListHead)中摘出來。但是, SetEvent函數并不會將線程從等待網上摘下來,是否要下來,由當前線程自己來決定。
關于強制喚醒
在APC專題講過,當我們插入一個用戶APC時(Alertable=1),當前線程是可以被喚醒的,但并不是真正的喚醒。
因為,如果當前的線程在等待網上,執行完用戶APC后,仍然要進入等待狀態。
總結
以上是生活随笔為你收集整理的4.WaitForSingleObject函数分析的全部內容,希望文章能夠幫你解決所遇到的問題。