Win32相关


记录一些学习WIN32知识的心得

Win32消息

Windows中的每一个动作都是一个 事件

而为了记录这些时间 产生了消息这么一个结构

消息结构

/*
 * Message structure
 */
typedef struct tagMSG {
    HWND        hwnd; 
    UINT        message;
    WPARAM      wParam;
    LPARAM      lParam;
    DWORD       time;
    POINT       pt;
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

hwnd

窗口句柄 用于标识消息所属的窗口

message

消息编号 表示消息的类型

wParam

消息参数 用于进一步解释消息

lParam

消息参数 用于进一步解释消息

time

触发时间

pt

类型为POINT类 结构如下

typedef struct tagPOINT
{
    LONG  x;
    LONG  y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;

用于记录消息位置

消息机制

  • 系统队列

    系统会维护一个队列 消息在里面排队

    这个系统队列会对消息进行分流

  • 应用队列

    将消息通过窗口句柄发给对应的应用程序

    应用程序也会有一个消息队列

  • 消息循环

    在这个队列里应用程序会通过循环对每个消息类型进行筛选 对关心的类型执行自己的处理函数

    如果是不关心的消息类型 就交给系统处理

Win32窗口

窗口结构

typedef struct tagWNDCLASSA {
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCSTR      lpszMenuName;
    LPCSTR      lpszClassName;
} WNDCLASSA, *PWNDCLASSA, NEAR *NPWNDCLASSA, FAR *LPWNDCLASSA;

包含窗口的各种属性

lpfnWndProc

重要 窗口消息处理函数

hInstance

lpszClassName

必要 窗口名字

创建自定义窗口步骤

  • 创建好窗口的结构体
  • 通过RegisterClass对窗口进行注册(通知Windows)
  • 在需要调用CreateWindow创建窗口

Win32IPC对象

对象概括

  • 已经学到的有进程、线程、互斥体、事件、信号量

  • 内核对象都有已通知和未通知两种状态

    比如说创建事件时第二个参数是是否开启手动模式(FALSE自动将已通知转换为未通知) 第三个参数是初始状态

    想要同时读取就开手动模式(让大家都能读) 想要互斥写就需要开启自动复位(一个开始写另一个需要等待)

  • 内核对象都可以跨进程

    比如说对互斥的控制 临界区只能在单个进程内使用 而互斥体可以跨进程

    但缺点是 内核对象性能较差 (因为需要进入到0环)

线程 Thread

线程可以说是进程要跑起来的基础 , 这里可以详细讲一下

创建线程

函数体如下

//创建进程
HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,//安全属性
  SIZE_T                  dwStackSize,		//分配栈大小
  LPTHREAD_START_ROUTINE  lpStartAddress,	//线程处理函数
  __drv_aliasesMem LPVOID lpParameter,		//传递给线程处理函数的参数
  DWORD                   dwCreationFlags,	//A pointer to a variable to be passed to the thread.
  LPDWORD                 lpThreadId		//The flags that control the creation of the thread.
);

我们可以看到, 为了成功创建线程, 我们通常需要先准备好一个线程处理函数, 这个线程函数需要满足一定的格式

继续往下看

线程处理函数

类似于消息框也需要一个消息框处理函数, 创建一个线程也需要一个线程处理函数

函数体形式应当如下

DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {...}

互斥体 Mutex

基本就是临界区(Critical Section)一样的功能, 区别就是一个是内核对象, 另一个是普通进程内的对象

//创建互斥体
HANDLE WINAPI CreateMutex(
  _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_     BOOL                  bInitialOwner,	//初始状态
  _In_opt_ LPCTSTR               lpName
);

//进入互斥体
HANDLE WINAPI OpenMutex(
  _In_ DWORD   dwDesiredAccess,
  _In_ BOOL    bInheritHandle,
  _In_ LPCTSTR lpName
);

//释放互斥体
BOOL WINAPI ReleaseMutex(
  _In_ HANDLE hMutex
);

事件 Event

//创建事件
HANDLE WINAPI CreateEvent(
  _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
  _In_     BOOL                  bManualReset,	//是否开启手冲模式
  _In_     BOOL                  bInitialState,	//设置初始状态
  _In_opt_ LPCTSTR               lpName
);
//例子
f_Consumed = CreateEvent(NULL, TRUE, TRUE, NULL);
//设置事件状态为TRUE
SetEvent(f_Consumed);
//关闭句柄
CloseHandle(f_Consumed);
  • Q: 什么时候会用到手冲模式呢?

  • A: 一般情况不会用到, 除非想让大家任意访问, 但这样存在的意义也不大了, 所以一般都是关闭手冲模式的, 来实现互斥用的

信号量 Semaphore

//创建
HANDLE g_Semaphore = HANDLE CreateSemaphore(		
		
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,		
		
  LONG lInitialCount,		//初始发放资源数目
		
  LONG lMaximumCount,		//最大并行资源数目
		
  LPCTSTR lpName		
		
);		

//申请一个空闲区域, 信号量第二个参数-1
WaitForSingleObject(g_Semaphore, INFINITE);

//释放,第二个参数表示释放后空闲的资源数目
ReleaseSemaphore(g_Semaphore, 1, NULL)

线程Context

线程之间互相切换的时候状态

这个结构就有了保存其线程寄存器状态的作用

使用方法

  • 先定义CONTEXT结构 依据想要获取的值对成员ContextFlags进行赋值
  • 调用GetThreadContext, 就可以在定义的CONTEXT结构看到想要的寄存信息了

进程就是4GB 线程就是EIP

跨进程的互斥和同步

互斥就是同一时刻不同访问

同步就是在一个执行之前需要保证另外一个优先执行 也就是要达到按序访问的目的

在学到的内核对象中 做一些小总结

实现互斥的工具

单进程可以有临界区 或者自己实现

这里主要还是讨论跨进程的内核对象

互斥体, 事件, 信号量都可以作互斥

  • 互斥体: 作用和最基本的临界区一致
  • 事件: 在临界区功能的基础上, 能够实现简单的进程同步(例如利用两个事件来解决生产者-消费者问题)
  • 信号量: 在可以实现临界区的基础上, 信号量更加灵活, 例如可以同时让有限个线程进入临界区

实现同步的工具

  • 事件: 在临界区功能的基础上, 能够实现简单的进程同步(例如利用两个事件来解决生产者-消费者问题)
  • 学习中

近期重新整理


Author: Luluting
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Luluting !
  TOC