1. 程式人生 > >零基礎逆向工程36_Win32_10_互斥體_ForSingleObject_WaitForMultipleObjects

零基礎逆向工程36_Win32_10_互斥體_ForSingleObject_WaitForMultipleObjects

mil 對象數組 pre seh 創建 count ebo 功能說明 建立

1 引言

講了第二個內核對象,互斥體。前面已經學過一個內核對象,線程。這節講兩個函數,WaitForSingleObject()和WaitForMultipleObjects()。因此這兩個函數是根據內核對象的狀態來進行操作的。

2 ForSingleObject()

DWORD WaitForSingleObject(
  HANDLE hHandle,        // handle to object
  DWORD dwMilliseconds   // time-out interval
);

功能說明:
等待函數可使線程自願進入等待狀態,直到一個特定的內核對象變為已通知狀態為止.

hHandle:
內核對象句柄,可以是進程也可以是線程.

dwMilliseconds:
等待時間,單位是毫秒 INFINITE(-1)一直等待

返回值:
WAIT_OBJECT_0(0) 等待對象變為已通知
WAIT_TIMEOUT(0x102) 超時

特別說明:
1、內核對象中的每種對象都可以說是處於已通知或未通知的狀態之中
2、這種狀態的切換是由Microsoft為每個對象建立的一套規則來決定的
3、當線程正在運行的時候,線程內核對象處於未通知狀態
4、當線程終止運行的時候,它就變為已通知狀態
5、在內核中就是個BOOL值,運行時FALSE 結束TRUE

代碼演示

DWORD WINAPI ThreadProc1(LPVOID lpParameter)    
{     
   for(int i=0;i<5;i++) 
   {  
      printf("+++++++++\n");
      Sleep(1000);
   }  
   return 0;   
}     
      
int main(int argc, char* argv[])    
{     
      
   //創建一個新的線程  
   HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,   
      NULL, 0, NULL);
      
   DWORD dwCode = ::WaitForSingleObject(hThread1, INFINITE);   
      
   MessageBox(0,0,0,0); 
      
   return 0;   
}     

3 和WaitForMultipleObjects()

DWORD WaitForMultipleObjects(
  DWORD nCount,             // number of handles in array
  CONST HANDLE *lpHandles,  // object-handle array
  BOOL bWaitAll,            // wait option
  DWORD dwMilliseconds      // time-out interval
);

功能說明:同時查看若幹個內核對象的已通知狀態

nCount:要查看內核對象的數量

lpHandles:內核對象數組

bWaitAll:等到類型 TRUE 等到所有變為已通知 FALSE 只要有一個變為已通知

dwMilliseconds:超時時間

INFINITE一直等待

返回值:
bWaitAll為TRUE時,返回WAIT_OBJECT_0(0) 代碼所以內核對象都變成已通知
bWaitAll為FALSE時,返回最先變成已通知的內核對象在數組中的索引

WAIT_TIMEOUT(0x102)

代碼演示:

DWORD WINAPI ThreadProc1(LPVOID lpParameter)    
{     
   for(int i=0;i<5;i++) 
   {  
      printf("+++++++++\n");
      Sleep(1000);
   }  
   return 0;   
}     
      
DWORD WINAPI ThreadProc2(LPVOID lpParameter)    
{     
   for(int i=0;i<3;i++) 
   {  
      printf("---------\n");
      Sleep(1000);
   }  
      
   return 0;   
}     
      
      
int main(int argc, char* argv[])    
{     
      
   HANDLE hArray[2]; 
      
   //創建一個新的線程  
   HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,   
      NULL, 0, NULL);
      
   //創建一個新的線程  
   HANDLE hThread2 = ::CreateThread(NULL, 0, ThreadProc2,   
      NULL, 0, NULL);
      
   hArray[0] = hThread1;   
   hArray[1] = hThread2;   
      
   DWORD dwCode = ::WaitForMultipleObjects(2, hArray,FALSE,INFINITE);   
      
   MessageBox(0,0,0,0); 
      
   return 0;   
}     

4 跨進程的線程控制與互斥體

進程一:
HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");

進程二:
HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
WaitForSingleObject(g_hMutex,INFINITE);

//邏輯代碼
ReleaseMutex(g_hMutex);

進程三:
HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
WaitForSingleObject(g_hMutex,INFINITE);

//邏輯代碼
ReleaseMutex(g_hMutex);

互斥體與臨界區的區別:
1、臨界區只能用於單個進程間的線程控制.
2、互斥體可以設定等待超時,但臨界區不能.
3、線程意外終結時,Mutex可以避免無限等待.
4、Mutex效率沒有臨界區高.

5 練習項目

做一個搶紅包項目,要求如下

第一步:在第一個文本框中輸入一個值,比如1000         
第二步:點擊搶紅包,同時創建3個線程,每個線程循環進行搶紅包的操作,每次搶50    
第三步:使用Mutex進行線程控制,當第一個文本框中的值<50時,強紅包線程結束.       
特別說明:        
1、四個文本框中的值總和應該為1000  
2、強紅包線程每次延時50毫秒. 
3、使用WaitForMultipleObjects監聽所有線程,當線程全部結束後       
   調用CloseHandle關閉句柄. 

零基礎逆向工程36_Win32_10_互斥體_ForSingleObject_WaitForMultipleObjects