zoukankan      html  css  js  c++  java
  • 零基础逆向工程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放入缓冲区
    ",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放入缓冲区
    ",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;
    }
    
    

  • 相关阅读:
    Kotlin入门(20)几种常见的对话框
    Kotlin入门(19)Android的基础布局
    Kotlin入门(18)利用单例对象获取时间
    Kotlin入门(17)等式判断的情况
    Kotlin入门(16)容器的遍历方式
    Kotlin入门(15)独门秘笈之特殊类
    Android Studio Gradle被墙bug总结
    unity常用的坐标系转换
    欧拉角与万向节死锁
    Unity导出Gradle工程给Android Studio使用
  • 原文地址:https://www.cnblogs.com/flatcc/p/7868103.html
Copyright © 2011-2022 走看看