Windows事件等待学习笔记(二)—— 线程等待与唤醒
Windows事件等待學習筆記(二)—— 線程等待與喚醒
- 要點回顧
- 等待與喚醒機制
- 可等待對象
- 可等待對象的差異
- 線程與等待對象
- 一個線程等待一個對象
- 實驗
- 第一步:編譯并運行以下代碼
- 第二步:在WinDbg中找到該進程
- 第三步:查看線程信息
- 一個線程等待多個對象
- 實驗
- 第一步:編譯并運行以下代碼
- 第二步:在WinDbg中找到該進程
- 第三步:查看線程信息
- 第四步:查看等待塊具體細節
- 等待網
- 總結
要點回顧
之前學習了如何自己實現臨界區以及什么是自旋鎖,這兩種同步方案在線程無法進入臨界區時都會讓當前線程進入等待狀態。
一種是通過Sleep函數實現的,一種是通過讓當前的CPU“空轉”實現的,但這兩種等待方式都有局限性:
思考:有沒有更加合理的等待方式,只有在條件成熟的時候才將當前線程喚醒?
等待與喚醒機制
描述:在Windows中,一個線程可以通過等待一個或者多個可等待對象,從而進入等待狀態,另一個線程可以在某些時刻喚醒等待這些對象的其他線程
可等待對象
在Windbg中查看以下結構體:
dt _KPROCESS
dt _KTHREAD
dt _KTIMER
dt _KSEMAPHORE
dt _KEVENT
dt _KMUTANT
dt _FILE_OBJECT
總結
可等待對象的差異
WaitForSingleObject(3環)
↓
NtWaitForSingleObject(內核)
↓
KeWaitForSingleObject(內核) //核心功能
線程與等待對象
描述:一個線程可以等待一個對象,也可以等待多個對象
一個線程等待一個對象
實驗
第一步:編譯并運行以下代碼
#include <stdio.h> #include <windows.h>HANDLE hEvent[2];DWORD WINAPI ThreadProc(LPVOID lpParamter) {::WaitForSingleObject(hEvent[0], -1);printf("ThreadProc函數執行\n");return 0; }int main(int argc, char* argv[]) {hEvent[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL); //創建一個可等待對象 _KEVENT::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, NULL, 0, NULL);getchar();return 0; }第二步:在WinDbg中找到該進程
!process 0 0
第三步:查看線程信息
查看 _KTHREAD
查看 _KWAIT_BLOCK
一個線程等待多個對象
實驗
第一步:編譯并運行以下代碼
#include <stdio.h> #include <windows.h>HANDLE hEvent[2];DWORD WINAPI ThreadProc(LPVOID lpParamter) {::WaitForMultipleObjects(2, hEvent, FALSE, -1);printf("ThreadProc函數執行\n");return 0; }int main(int argc, char* argv[]) {hEvent[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL); //創建可等待對象hEvent[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL); //創建可等待對象::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, NULL, 0, NULL);getchar();return 0; }第二步:在WinDbg中找到該進程
!process 0 0
第三步:查看線程信息
dt _KTHREAD 862b3340
共有兩個等待塊:
注意:此時WaitType字段的值仍是1,這是因為只要有一個對象滿足條件,當前線程就可以被喚醒(詳見第一步代碼部分)
第四步:查看等待塊具體細節
代碼中創建的對象為 _KEVENT,所以 _KWAIT_BLOCK +0x00C Object 指向 _KEVENT +0x000 _DISPATCHER_HEADER
kd> dt _DISPATCHER_HEADER 0x86015db8 nt_400000!_DISPATCHER_HEADER+0x000 Type : 0 ''+0x001 Absolute : 0x21 '!'+0x002 Size : 0x4 ''+0x003 Inserted : 0x86 ''+0x004 SignalState : 0n0+0x008 WaitListHead : _LIST_ENTRY [ 0x862b33c8 - 0x862b33c8 ]WaitListHead:雙向鏈表,圈著所有等待塊的WaitListEntry
等待網
總結
總結
以上是生活随笔為你收集整理的Windows事件等待学习笔记(二)—— 线程等待与唤醒的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows事件等待学习笔记(一)——
- 下一篇: Windows事件等待学习笔记(三)——