1. 程式人生 > >零基礎逆向工程37_Win32_10_事件_線程同步

零基礎逆向工程37_Win32_10_事件_線程同步

hcl word security 臨界區 運行 創建 and ima har

1 內核對象

前面已經學過線程和互斥體兩個內核對象。此節講了事件這個內核對象。前面提出了內核對象這個概念,可能不太清晰,簡單來說內核對象就是系統層的東西。

1.1 小結內核對象:

進程、線程、事件、互斥體、文件、文件映射等。

1.2 事件內核對象的創建

HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");
HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");

1.3 事件內核對象的獲取

HANDLE OpenEvent(
  DWORD dwDesiredAccess,  // access
  BOOL bInheritHandle,    // inheritance option
  LPCTSTR lpName          // object name
);

HANDLE g_hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "XYZ");

HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");

1.4 內核對象的銷毀

BOOL CloseHandle(HANDLE hobj);

(1)、當沒有其他程序引用時,系統會銷毀內核對象(使用數量).
(2)、內核對象的生命周期,可能比創建它的對象要長.

2 事件對象

2.1 事件對象的創建

HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全屬性 NULL時為系統默認
  BOOL bManualReset,                       // TRUE 通過調用ResetEvent將事件對象標記為未通知
  BOOL bInitialState,                      // TRUE 已通知狀態  FALSE未通知狀態
  LPCTSTR lpName                           // 對象名稱 以NULL結尾的字符串
);

2.2 事件對象的控制

BOOL SetEvent(HANDLE hEvent);

2.3 關閉時間對象句柄

CloseHandle();

2.4 線程控制實驗:只讀形式的線程控制

HANDLE g_hEvent;

HWND hEdit1;
HWND hEdit2;
HWND hEdit3;
HWND hEdit4;
HANDLE hThread1;
HANDLE hThread2;
HANDLE hThread3;
HANDLE hThread4;

DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
  //創建事件
  //默認安全屬性  手動設置未通知狀態(TRUE)  初始狀態未通知 沒有名字
  g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  HANDLE hThread[3];
  //創建3個線程
  hThread[0] = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
  hThread[1] = ::CreateThread(NULL, 0, ThreadProc3, NULL, 0, NULL);
  hThread[2] = ::CreateThread(NULL, 0, ThreadProc4, NULL, 0, NULL);

  //設置文本框的值
  SetWindowText(hEdit1,"1000");

  //設置事件為已通知
  SetEvent(g_hEvent);

  //等待線程結束 銷毀內核對象
  WaitForMultipleObjects(3, hThread, TRUE, INFINITE);
  CloseHandle(hThread[0]);
  CloseHandle(hThread[1]);
  CloseHandle(hThread[2]);
  CloseHandle(g_hEvent);

  return 0;
}

DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
  TCHAR szBuffer[10] = {0};

  //當事件變成已通知時
  WaitForSingleObject(g_hEvent, INFINITE);

  //讀取內容
  GetWindowText(hEdit1,szBuffer,10);

  SetWindowText(hEdit2,szBuffer);

  return 0;
}
DWORD WINAPI ThreadProc3(LPVOID lpParameter)
{
  TCHAR szBuffer[10] = {0};

  //當事件變成已通知時
  WaitForSingleObject(g_hEvent, INFINITE);

  //讀取內容
  GetWindowText(hEdit1,szBuffer,10);

  SetWindowText(hEdit3,szBuffer);

  return 0;
}
DWORD WINAPI ThreadProc4(LPVOID lpParameter)
{
  TCHAR szBuffer[10] = {0};

  //當事件變成已通知時
  WaitForSingleObject(g_hEvent, INFINITE);

  //讀取內容
  GetWindowText(hEdit1,szBuffer,10);

  SetWindowText(hEdit4,szBuffer);

  return 0;
}

3 線程同步

3.1 什麽是線程同步?

同步就是協同步調,按預定的先後次序進行運行。如:你說完,我再說。

如進程、線程同步,可理解為進程或線程A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B運行;B依言執行,再將結果給A;A再繼續操作。

[摘自百度百科]

3.2 事件和臨界區

HANDLE g_hSet, g_hClear;
int g_Max = 10;
int g_Number = 0;

//生產者線程函數
DWORD WINAPI ThreadProduct(LPVOID pM)
{
    for (int i = 0; i < g_Max; i++)
    {
        WaitForSingleObject(g_hSet, INFINITE);
        g_Number = 1;
        DWORD id = GetCurrentThreadId();
        printf("生產者%d將數據%d放入緩沖區\n",id, g_Number);
        SetEvent(g_hClear);
    }
    return 0;
}

//消費者線程函數
DWORD WINAPI ThreadConsumer(LPVOID pM)
{
    for (int i = 0; i < g_Max; i++)
    {
        WaitForSingleObject(g_hClear, INFINITE);
        g_Number = 0;
        DWORD id = GetCurrentThreadId();
        printf("----消費者%d將數據%d放入緩沖區\n",id, g_Number);
        SetEvent(g_hSet);
    }
    return 0;
}

int main(int argc, char* argv[])
{

    HANDLE hThread[2];

    g_hSet = CreateEvent(NULL, FALSE, TRUE, NULL);
    g_hClear = CreateEvent(NULL, FALSE, FALSE, NULL);

    hThread[0] = ::CreateThread(NULL, 0, ThreadProduct, NULL, 0, NULL);
    hThread[1] = ::CreateThread(NULL, 0, ThreadConsumer, NULL, 0, NULL);

    WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
    CloseHandle(hThread[0]);
    CloseHandle(hThread[1]);

    //銷毀
    CloseHandle(g_hSet);
    CloseHandle(g_hClear);

  return 0;
}

技術分享圖片

零基礎逆向工程37_Win32_10_事件_線程同步