06 互斥體

1、爲什麼要由互斥體:等待對象被遺棄

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

但需要明確的是,這幾個對象都是內核對象,這就意味着,通過這幾個對象可以用來進行跨進程間的線程同步控制。比如:

A進程中的X線程

B進程中的Y線程

都等待Z對象

極端情況:

如果B進程裏的Y線程還沒來得及調用修改SignalState的函數(如SetEvent),那麼等待對象Z將被遺棄,這也就意味着X進程中的線程將永遠等待下去。

這種極端的情況,時間和信號量是無法解決的。如果用互斥體,B進程中的Y線程沒有來得及修改,系統會幫忙修改。

2、爲什麼要由互斥體:重入

如果需要多次重入臨界區,用互斥體就不會死鎖。互斥體與時間和信號量的第二個區別就是允許重複進入臨界區。
在這裏插入圖片描述
爲什麼互斥體可以重複進入臨界區。

3、MUTANT結構體介紹

nt!_KMUTANT
+0x000 Header : _DISPATCHER_HEADER
+0x010 MutantListEntry : _LIST_ENTRY
+0x018 OwnerThread : Ptr32 _KTHREAD
+0x01c Abandoned : UChar
+0x01d ApcDisable : UChar

MutantListEntry :

擁有互斥體線程( KTHREAD +0x010 MutantListHead : _LIST_ENTRY)是個鏈表頭,牽着所有線程。

OwnerThread :

正在擁有互斥體的線程

Abandoned :

是否已被放棄不用

ApcDisable :

是否禁用內核APC

4、CreateMutex函數

HANDLE CreateMutex(LPSECURITY_ATTRIBUTE SlpMutexAttributes,//指向安全屬性的指針

BOOL bInitailOwner, //初始化互斥對象的所有者

LPCTSTR lpName //指向互斥體對象名的指針

);

CreateMutex–>NtCreateMutant(內核函數)–>KeInitializeMutant(內核函數)

初始化MUTANT結構體:

MUTANT.Header.Type = 2;

MUTANT.Header.SignalState = bInitailOwner ? 0 : 1;

MUTANT.OwnerThread = 當前線程 or NULL;

MUTANT.Abandoned = 0;

MUTANT.ApcDisable= 0;

bInitailOwner == TRUE 將當前的互斥體掛入噹噹前線程的互斥體鏈表中( +0x010 MutantListHead : _LIST_ENTRY)

5、ReleaseMutex函數

BOOL WINAPI ReleaseMutex(HANDLE hMutex);

ReleaseMutex–>NtReleaseMutant–>KeReleaseMutant

正常調用時:

MUTANT.Header.SignalState++;

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

6、如何解決重入的問題

nt!_KMUTANT
+0x000 Header : _DISPATCHER_HEADER
+0x010 MutantListEntry : _LIST_ENTRY
+0x018 OwnerThread : Ptr32 _KTHREAD
+0x01c Abandoned : UChar
+0x01d ApcDisable : UChar

OwnerThread:正在擁有互斥體的線程

(參見KeWaitForSingleObject)

7、如何解決等待對象被遺棄的問題

nt!_KMUTANT
+0x000 Header : _DISPATCHER_HEADER
+0x010 MutantListEntry : _LIST_ENTRY
+0x018 OwnerThread : Ptr32 _KTHREAD
+0x01c Abandoned : UChar
+0x01d ApcDisable : UChar

MutantListEntry :

擁有互斥體線程( KTHREAD +0x010 MutantListHead : _LIST_ENTRY)是個鏈表頭,牽着所有線程。

Abandoned :

是否已被放棄不用

8、如何解決等帶對象被遺棄的問題

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

if(Abandon == false)//正常被調用

{

​ MUTANT.Header.SignalState++;

}

else

{

​ MUTANT.Header.SignalState = 1;

​ MUTANT.OwnerThread = NULL;

}

if( MUTANT.Header.SignalState == 1)

{

​ MUTANT.OwnerThread = NULL;

​ //從當前線程互斥體鏈表中將當前互斥體移除

}

(參見KeReleaseMutant)
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章