日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

《Windows via C/C++》学习笔记 —— “线程同步”之“检测死锁”

發布時間:2024/9/5 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Windows via C/C++》学习笔记 —— “线程同步”之“检测死锁” 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  本來這篇內容在書中是在“其他線程同步函數”這一節中的。這節中介紹了另外的幾個等待函數,比如WaitForInputIdle、MsgWaitForMultipleObjects、WaitForDebugEvent,感覺用途不大,只有SignalObjectAndWait這個函數用途比較大,該函數筆者已經在前面的“等待函數”這一篇中寫過了。

  本篇主要討論這本書新增加的內容,就是Windows Vista中提供的調查死鎖的方法。

?

  在Windows Vista中,提供了用來“檢測線程死鎖”的一組API,Jeffrey Richter先生在書中將其稱為“Wait Chain Traversal”(WCT)API。查看了網上的翻譯,叫做“等待鏈遍歷”API函數,我也不知道這么翻譯是否正確或權威,就姑且這么叫著吧,下面簡稱為WCT。

  WCT函數允許你列出“鎖”,并檢測死鎖,無論是單個進程的,還是跨進程的。Windows對以下線程同步機制的鎖保持著跟蹤:

可能的鎖

描述

關鍵代碼段

Windows對關鍵代碼段屬于哪個線程保持著跟蹤

互斥內核對象

Windows對互斥內核對象屬于哪個線程保持著跟蹤,即使互斥內核對象被丟棄

進程和線程

Windows對一個線程正在等待哪個進程或線程保持著跟蹤,另外跟蹤進程和線程是否終止

SendMessage

Windows保持跟蹤正在等待SendMessage函數返回的線程

COM初始化和調用

調用CoCreateInstance函數或COM對象的方法的線程被跟蹤

高級本地過程調用(ALPC)

在Windows Vista中,ALPC代替了LPC,新的沒有文檔的內核進程內部的通信(IPC)機制

?

  需要注意的是,讀寫鎖(SRWLock)同步機制沒有被WPC所跟蹤,另外某些內核對象,比如事件內核對象、信號量、等待定時器沒有被跟蹤。

?

  本書舉了一個例子來演示了WPC函數的使用。本人總結了下,主要通過以下幾個步驟來實現死鎖的檢測:

1、打開等待鏈:使用OpenThreadWaitChainSession函數

2、如果需要檢測COM的話:使用RegisterWaitChainCOMCallback函數

3、取得等待鏈信息:使用GetThreadWaitChain函數

4、關閉等待鏈:使用CloseThreadWaitChainSession函數

?

  首先,介紹一下OpenThreadWaitChainSession函數:

HWCT?OpenThreadWaitChainSession(
???DWORD?dwFlags,???????
//0表示同步,WCT_ASYNC_OPEN_FLAG表示異步
???PWAITCHAINCALLBACK?callback);???//異步的話要設置該回調函數指針

?

  該函數成功,返回一個HWCT類型的句柄,該句柄要傳遞給CloseThreadWaitChainSession函數,在最后釋放。如果失敗,該函數返回NULL。

  一般地,您總是希望從中調用RegisterWaitChainCOMCallback函數以注冊 CoGetCallState和CoGetActivationState這兩個COM函數,以便WCT能夠報告 COM所有權信息,由于并未記錄這些函數,您需要從ole32.dll通過GetProcAddress 獲得這些函數。本人認為,在您對WCT API進行初始化以查找COM死鎖時,WCT API 應自動處理這種細小問題。

?

VOID?WINAPI?RegisterWaitChainCOMCallback(
???__in??PCOGETCALLSTATE?CallStateCallback,???
//CoGetCallState函數地址
???__in??PCOGETACTIVATIONSTATE?
?????????????ActivationStateCallback????
//CoGetActivationState函數地址
);

?

  你可以使用如下代碼這樣使用RegisterWaitChainCOMCallback函數:

?

PCOGETCALLSTATE?CallStateCallback;??????//函數指針
PCOGETACTIVATIONSTATE?ActivationStateCallback;?????//函數指針

HMODULE?hOLE32DLL?
=?LoadLibrary(TEXT("OLE32.DLL"));//加載OLE32.DLL

//從ole32.dll中取得函數地址
CallStateCallback?=?(PCOGETCALLSTATE)
?????????????????????GetProcAddress(_hOLE32DLL,?
"CoGetCallState");
ActivationStateCallback?
=?(PCOGETACTIVATIONSTATE)
?????????????GetProcAddress(_hOLE32DLL,?
"CoGetActivationState");?

//在等待鏈中注冊COM函數
RegisterWaitChainCOMCallback(CallStateCallback,ActivationStateCallback);

?

  下面,第3步,使用GetThreadWaitChain函數取得等待鏈信息:

BOOL?WINAPI?GetThreadWaitChain(
???HWCT?hWctSession,??????????
//等待鏈句柄
???DWORD_PTR?pContext,?????//異步方法中回調函數的參數
???DWORD?dwFlags,??????????????//查詢類型(位或組合)
???DWORD?TID,????????????????????//要查詢的線程的線程ID
???PDWORD?pNodeCount,??????//返回值,指明等待鏈中的結點個數
???PWAITCHAIN_NODE_INFO?pNodeInfoArray,?????//返回值,等待鏈結點信息
???LPBOOL?pbIsCycle?????????????//返回值,TURE表示死鎖
);

?

  pNodeCount參數如果返回的DWORD數據值為0,表明一個問題產生了,比如拒絕訪問。這個時候可以調用GetLastError取得錯誤信息。

  這個函數中,pNodeInfoArray函數是一個WAITCHAIN_NODE_INFO結構的指針,該結構如下:

?

typedef?struct?_WAITCHAIN_NODE_INFO
{
????WCT_OBJECT_TYPE?ObjectType;??????????
//結點對象類型
????WCT_OBJECT_STATUS?ObjectStatus;???//結點對象狀態

????union?{
????????
struct?{
????????????WCHAR?ObjectName[WCT_OBJNAME_LENGTH];
????????????LARGE_INTEGER?Timeout;????
//?Not?implemented?in?v1
????????????BOOL?Alertable;???????????//?Not?implemented?in?v1
????????}?LockObject;

???????
struct?{
???????????DWORD?ProcessId;
???????????DWORD?ThreadId;
???????????DWORD?WaitTime;
???????????DWORD?ContextSwitches;
???????}?ThreadObject;
????};
}?WAITCHAIN_NODE_INFO,?
*PWAITCHAIN_NODE_INFO;

?

  該結構中的ObjectTyped成員,指明了當前等待鏈中的結點類型,ObjectStatus指明了當前該結點對象的狀態,兩者具體取值就看MSDN或本書吧。如果這個結點類型是一個“阻塞”狀態的線程,即ObjectTyped為WctThreadType的話,內部的ThreadObject成員即有效。

?

  最后,不要忘記調用CloseThreadWaitChainSession關閉WCT句柄。當然,如果用LoadLibrary函數加載了OLE23.dll文件的話,也要記得FreeLibrary函數來釋放。

?

  可以使用如下代碼處理等待鏈中的結點:

?

HWCT?hWCTSession?=?OpenThreadWaitChainSession(0,?NULL);
if?(hWCTSession?==?NULL)
?????
return?0;

//兩個COM的函數指針
PCOGETCALLSTATE?CallStateCallback;
PCOGETACTIVATIONSTATE?ActivationStateCallback;

HMODULE?hOLE32DLL?
=?LoadLibrary(TEXT("OLE32.DLL"));???//加載OLE32.DLL
if?(hOLE32DLL?==?NULL)
?????
return?0;

//從ole32.dll中取得兩個函數的地址
CallStateCallback?=?(PCOGETCALLSTATE)
?????????????????????GetProcAddress(_hOLE32DLL,?
"CoGetCallState");
ActivationStateCallback?
=?(PCOGETACTIVATIONSTATE)
?????????????????????GetProcAddress(_hOLE32DLL,?
"CoGetActivationState");

//注冊COM函數,使得WCT可以報告COM相關事件
RegisterWaitChainCOMCallback(CallStateCallback,ActivationStateCallback);

//在你需要處理的線程中:
DWORD?dwNodesInChain?=?0;?????//鏈中的結點個數
BOOL?bDeadlock?=?FALSE;???????//線程是否存在死鎖
WAITCHAIN_NODE_INFO?chain[WCT_MAX_NODE_COUNT];//WCT節點結構數組

//取得等待鏈信息,并判斷是否正確,TID為線程ID
if?(!GetThreadWaitChain(hWCTSession,?NULL,?WCTP_GETINFO_ALL_FLAGS,
?????????TID,?
&dwNodesInChain,?chain,?&bDeadlock))
{
?????
//函數調用失敗,在此處理
??????
//
?????return?0;
}

//?開始處理等待鏈
dwNodesInChain?=?min(dwNodesInChain,?WCT_MAX_NODE_COUNT);

if?(dwNodesInChain?==?0)?????//結點個數為0,可以調用GetLastError處理
?????return?0;

//可以在此處理本線程有關的等待鏈信息
if?(bDeadlock)
?????
//表明線程ID為TID的線程存在死鎖

//處理每個鏈中的節點
for?(DWORD?current?=?0;?current?<?dwNodesInChain;?++current)
{
?????
//在此處理練中每個結點信息
??????
//
}

FreeLibrary(hOLE32DLL);????
//釋放COM模塊
CloseThreadWaitChainSession(hWCTSession);????//關閉WCT

?

轉載于:https://www.cnblogs.com/wz19860913/archive/2008/08/15/1268901.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的《Windows via C/C++》学习笔记 —— “线程同步”之“检测死锁”的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。