Windows核心编程 --- 内核对象进行线程同步

1,等待函数WaitrForSingleObject(HANDLE , WaitTime),当等待的对象被触发时候返回值:

DWORD WINAPI WaitForSingleObject(
  _In_ HANDLE hHandle,
  _In_ DWORD  dwMilliseconds
);

    WAIT_OBJECT_0:表示对象被触发

    WAIT_TIMEOUT:表示等待超时

    WAIT_FAILED:    表示出错,比如传入了无效句柄

2,WaitForMultipleObjects可以同时检查多个内核对象的触发状态:

DWORD WINAPI WaitForMultipleObjects(
  _In_       DWORD  nCount,
  _In_ const HANDLE *lpHandles,
  _In_       BOOL   bWaitAll,
  _In_       DWORD  dwMilliseconds
);

nCount表示要检查的内核对象的数量

lpHandles表示检查的内核对象数组

bWaitAll表示是等待lpHandles中的nCount个对象全部变为触发状态返回还是只要一个变为触发状态就返回。

如果bWaitAll传入FALSE,那么返回值是WAIT_OBJECT_0 到 WAIT_OBJECT_0 + dwCount - 1之间的任意一个值。

如果在Wait的过程中一个已经触发的内核对象再次变为未触发状态,那么就还会继续等待这个对象触发才会返回。


自动重置事件对象:在WaitForXXX时,函数返回时候会将自动重置事件对象由触发状态变为未触发状态。

手动重置事件对象与自动重置事件对象区别是:自动重置事件触发时候只有一个等待事件的线程变为可调度,而手动重置对象触发时候所有等待的线程都会变为可调度。


3,创建事件内核对象:CreateEvent

HANDLE WINAPI CreateEvent(
  _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
  _In_     BOOL                  bManualReset,
  _In_     BOOL                  bInitialState,
  _In_opt_ LPCTSTR               lpName
);

第二个bManualReset为TRUE表示创建手动重置事件,为FALSE表示创建自动重置事件。

第三个bInitialState为TRUE表示事件初始化为触发状态。

第四个指定一个名字,其他进程可以通过OpenEvent或CreateEvent传入名字来打开同一个进程内核对象。

SetEvent :  设置事件为触发状态。

ResetEvent:设置事件为未触发状态。


4,CreateWaitableTimer:

HANDLE WINAPI CreateWaitableTimer(
  _In_opt_ LPSECURITY_ATTRIBUTES lpTimerAttributes,
  _In_     BOOL                  bManualReset,
  _In_opt_ LPCTSTR               lpTimerName
);

创建一个可等待的计时器内核对象,创建后处于未触发状态。

用SetWaitTimer可以让计时器处于触发状态。

BOOL WINAPI SetWaitableTimer(
  _In_           HANDLE           hTimer,
  _In_     const LARGE_INTEGER    *pDueTime,
  _In_           LONG             lPeriod,
  _In_opt_       PTIMERAPCROUTINE pfnCompletionRoutine,
  _In_opt_       LPVOID           lpArgToCompletionRoutine,
  _In_           BOOL             fResume
);
pDueTime表示计时器第一次触发的时间(本地时间绝对时间20xx-xx-xx),为负数表示相对时间,是100ns的整数倍,如果传入1秒就应该传入-10000000。

lPeriod表示的是计时器触发的间隔时间,如果为0表示触发一次后不再触发。

pfnCompletionRoutine表示设置的APC回调函数

CancleWaitableTimer表示取消指定的计时器。


5,APC调用

当SetWaitableTimer的调用线程处于可提醒状态时候(调用SleepEx , WaitForSingleObjectEx , WaitForMultipleObjectEx , MsgWaitForMultipleObjectsEx , SignalObjectAndWait)进入的等待状态,系统就会将函数的pfnCompletionRoutine添加进APC队列。


6,信号量:CreateSemaphoreEx

HANDLE WINAPI CreateSemaphoreEx(
  _In_opt_   LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  _In_       LONG                  lInitialCount,
  _In_       LONG                  lMaximumCount,
  _In_opt_   LPCTSTR               lpName,
  _Reserved_ DWORD                 dwFlags,
  _In_       DWORD                 dwDesiredAccess
);

使用计数:内核对象的使用计数

最大资源计数:最大的资源数量

当前资源计数:表示信号量当前可用资源的数量

ReleaseSemphore来增加当前信号量的资源计数


7,互斥量Mutex

CreateMutex , CreateMutexEx , OpenMutex

HANDLE WINAPI CreateMutex(
  _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_     BOOL                  bInitialOwner,
  _In_opt_ LPCTSTR               lpName
);
bInitialOwner为FALSE表示将互斥量的ID和递归计数设置为0,这表示处于触发状态,设置为TRUE表示将ID设置为调用线程的线程ID,并且递归计数设置为1,表示未触发状态。

使用计数:内核对象使用计数

线程ID:与互斥量所绑定的线程ID,如果处于触发状态则ID为0

递归计数:一个线程占用互斥量的次数

ReleaseMutex来释放互斥量


8,SignalObjectAndWait

DWORD WINAPI SignalObjectAndWait(
  _In_ HANDLE hObjectToSignal,
  _In_ HANDLE hObjectToWaitOn,
  _In_ DWORD  dwMilliseconds,
  _In_ BOOL   bAlertable
);
用于触发一个对象然后等待另一个对象,在内部会执行与ReleaseMutext,ReleaseSemaphore,SetEvent等价的操作。







猜你喜欢

转载自blog.csdn.net/a893574301/article/details/80787004