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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

7.互斥体

發布時間:2025/3/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 7.互斥体 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么要有互斥體:等待對象被遺棄

互斥體(MUTANT)與事件(EVENT)和信號量(SEMAPHORE)一樣,都可以用來·進行線程的同步控制。

但需要指出的是,這幾個對象都是內核對象,這就意味著,通過這些對象可以進行跨進程的線程同步控制,比如:

A進程中的X線程與B進程中的Y線程,它們可以共同使用一個內核對象來進行線程同步控制。

極端情況:
如果B進程的Y線程還沒有來得及調用修改SignalState的函數(如SetEvent)那么等待對象Z將被遺棄,這也就以為者x線程將永遠等下去!

但如果我們用的是互斥體這種情況就很好解決,即使你的B進程的Y線程還沒有來得及調用修改SignalState的函數,系統也會幫你修改。

因為創建了互斥體時,已經將互斥體已經將掛到了互斥體鏈表里,系統的函數可以通過binitialOwner查找到你當前線程所占用的互斥體。

當前線程并不維護事件與信號量,但是它維護互斥體對象

互斥體允許重入

上面調用了WaitForSingleObject等待對象是A,由于邏輯方面的要求后面有調用了WaitForMultipleObjects等待對象為A,B,C。

調用WaitForSingleObject(A)的時候已經將A對象的SignalState改為0了沒有信號了,那就必須在你的WaitForSingleObject(A)執行完畢后調用SetEvent來修改SignalState為1。

這時就出問題了由于圖上的A這時是沒有信號的,這時你的代碼將永遠停留在WaitForMultipleObjects(A,B,C)這個位置,這種情況就叫死鎖

解決方案:
如果你需要多次重復進入臨界區的話,這時你的A對象是互斥體就不會出現死鎖。

互斥體與事件/信號量的第二個區別就是它允許重復進入臨界區。

MUTANT結構體介紹

kd> dt _KMUTANT nt!_KMUTANT+0x000 Header : _DISPATCHER_HEADER+0x010 MutantListEntry : _LIST_ENTRY+0x018 OwnerThread : Ptr32 _KTHREAD //當前互斥體對象所屬線程+0x01c Abandoned : UChar+0x01d ApcDisable : UChar+0x010 MutantListEntry 擁有互斥體線程(KTHREAD+0x010 MutantListHead)是個鏈表頭**圈著所有互斥體**+0x018 OwnerThread: 正在擁有互斥體的線程 +0x01c Abandoned: 是否已經被放棄不用 +0x01d ApcDisable: 是否禁用內核APC 0不禁用 1禁用 (3環)Mutant 對應內核函數 NtCreateMutant ApcDisable = 0 (0環)Mutex 對應內核函數 NtCreateMutex ApcDisable = 1 (參見 KeWaitForsingleObject 函數)

CreateMutex創建互斥體

HANDLE CreateMutex (LPSECURITYATTRIBUTE SlpMutexAttributes, //指向安全屬性的指針 BOOL bnitialOwner, //初始化互斥對象的擁有者 LPCTSTR IpName //指向互斥對象名的指針 ) 參數2:TRUE代表就是當前線程的, FALSE代表這個互斥體不是當前線程只是將他創建出來 CreateMutex -> NtCreateMutant(內核函數) -> KelnitializeMutant(內核函數) 初始化MUTANT結構體: MUTANT.Header.Type=2; MUTANT.Header.SianalState =binitialOwner ?0:1;//參數2初始值為true它就為0 MUTANT.OwnerThread=當前線程 or NULL;//參數2初始值為true當前線程,false就是0 MUTANT.Abandoned = 0; MUTANT.ApcDisable=0;

如果 blnitialOwner == TRUE 將當前互斥體掛入到當前線程的互斥體鏈表(KTHREAD+0x010 MutantListHead)

ReleaseMutex釋放臨界區

BOOL WINAPI ReleaseMutex(HANDLE hMutex);

ReleaseMutex ->NtReleaseMutant ->KeReleaseMutant

正常調用時:
MUTANT.Header.SignalState++;

如果SignalState=1(有信號了) 說明其他進程可用了 將該互斥體從線程鏈表中移除。

互斥體解決等待對象被遺棄問題

_KMUTANT+0x000 Header : _DISPATCHER_HEADER+0x010 MutantListEntry : _LIST_ENTRY+0x018 OwnerThread : Ptr32 _KTHREAD //當前互斥體對象所屬線程+0x01c Abandoned : UChar+0x01d ApcDisable : UChar+0x010 MutantListEntry: 擁有互斥體線程(KTHREAD+0x010 MutantListHead)是個鏈表頭圈著所有互斥體 +0x01c Abandoned: 是否已經被放棄不用

MmUnloadSystemlmage -> KeReleaseMutant(X, Y,Abandon,Z)//是否被丟棄

KeReleaseMutant的第3個參數可以知道是被正常釋放,還是被丟棄的
正常是FALSE
丟棄是TRUE,系統會直接將SignalState置為有信號狀態

if(Abandon == false) //正常調用 {MUTANT.Header.SignalState++; }else//丟棄 {MUTANT.Header.SignalState == 1;MUTANT.OwnerThread == NULL; } if(MUTANT.Header.SignalState==1) {MUTANT.OwnerThread == NULL;//從當前線程互斥體鏈表中將當前互斥體移除 }

進入互斥體

總結

以上是生活随笔為你收集整理的7.互斥体的全部內容,希望文章能夠幫你解決所遇到的問題。

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