零基础逆向工程37_Win32_11_事件_线程同步

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;
}

posted @ 2017-11-20 20:26  flatcc  阅读(303)  评论(0编辑  收藏  举报