零基礎逆向工程36_Win32_10_互斥體_ForSingleObject_WaitForMultipleObjects
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