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