《Windows核心编程》学习笔记(9)– 用内核对象进行线程同步
等待函数
等待函数使一个线程自愿进入等待,直到指定的内核对象被触发为止。
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
DWORD WaitForMultipleObjects(
DWORD nCount,
CONST HANDLE* lpHandles,
BOOL fWaitAll,
DWORD dwMilliseconds
);
时间内核对象
创建时间内核对象:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPTSTR lpName
);
1.参数bManualReset 用来告诉系统应该创建一个手动重置事件(TRUE)还是一个自动重置事件(FALSE).
手动重置对象触发的时候会唤醒等待该对象的全部线程。
而自动重置对象触发的时候只会唤醒等待该线程对象中的其中一个线程。
2.参数bInitialState 表示应该将事件初始化为触发状态(TRUE)还是未触发状态(FALSE).
其他进程中的线程访问别的进程中创建的事件对象:
HANDLE OpenEvent(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
使事件变成触发状态:
BOOL SetEvent(HANDLE hEvent );
把事件变成未触发状态:
BOOL ResetEvent(HANDLE hEvent );
BOOL PulseEvent(
HANDLE hEvent
);
该函数会先触发事件然后立即将其恢复到未触发的状态。此函数用处并不大。
可等待的计时器内核对象
创建可等待的计数器:
HANDLE WINAPI CreateWaitableTimer(
__in LPSECURITY_ATTRIBUTES lpTimerAttributes,
__in BOOL bManualReset,
__in LPCTSTR lpTimerName
);
参数bManualReset 表示要创建一个手动重置计数器还是自动重置计数器。
得到一个已经存在的可等待计数器的句柄:
HANDLE WINAPI OpenWaitableTimer(
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in LPCTSTR lpTimerName
);
在创建可等待计数器对象时,它总是处于未触发状态。触发计时器:
BOOL WINAPI SetWaitableTimer(
__in HANDLE hTimer,
__in const LARGE_INTEGER* pDueTime,
__in LONG lPeriod,
__in PTIMERAPCROUTINE pfnCompletionRoutine,
__in LPVOID lpArgToCompletionRoutine,
__in BOOL fResume
);
参数pDueTime表示计时器第一次触发时间应该是在什么时候。
参数lPeriod 表示在第一次触发之后,计时器应该以怎样的频度触发。
例如:将定时器的第一次报时的时间设置在 2002年1月1日的下午1点钟,然后每隔6小时报时一次
我们除了可以给计时器第一次触发的时间指定一个绝对时间外,也可以让定时器在一个相对于调用SetWaitableTimer的时间进行触发。只需要在pDueTime参数中传递一个负值。传递的值必须是以100ns为间隔。由于我们通常并不以100 ns的间隔来思考问题,因此我们要说明一下 100ns的具体概念: 1s = 1000 ms = 1000000?s = 10000000个100ns 。
下面的代码用于将定时器的第一次触发设置在调用SetWaitableTimer函数的5s后:
LARGE_INTEGER li;
HANDLE h_Timer;
h_Timer = CreateWaitableTimer(NULL, FALSE, NULL);
CreateThread(NULL, 0, Proc, NULL, 0, NULL);
const int nTimerUnitsPerSecond = 10000000;
li.QuadPart = -(5 * nTimerUnitsPerSecond);
SetWaitableTimer(h_Timer, &li, 6 * 60 * 60 * 1000, NULL, NULL, FALSE);
信号量内核对象
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
例如:HANDLE hSemaphore = CreateSemaphore(NULL, 0, 5, NULL);
得到一个已经存在的信号量的句柄:
HANDLE WINAPI OpenSemaphore(
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in LPCTSTR lpName
);
递增信号量的当前计数:
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
参数lReleaseCount 的值会加到信号量的当前计数上。
参数lpPreviousCount 中返回当前资源计数的原始值。
互斥量内核对象
创建一个互斥量:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
释放互斥量对象:
BOOL ReleaseMutex( HANDLE hMutex );
其他的线程同步函数
DWORD WINAPI WaitForInputIdle(
__in HANDLE hProcess,
__in DWORD dwMilliseconds
);
DWORD WINAPI MsgWaitForMultipleObjects(
__in DWORD nCount,
__in const HANDLE* pHandles,
__in BOOL bWaitAll,
__in DWORD dwMilliseconds,
__in DWORD dwWakeMask
);
BOOL WINAPI WaitForDebugEvent(
__out LPDEBUG_EVENT lpDebugEvent,
__in DWORD dwMilliseconds
);
DWORD WINAPI SignalObjectAndWait(
__in HANDLE hObjectToSignal,
__in HANDLE hObjectToWaitOn,
__in DWORD dwMilliseconds,
__in BOOL bAlertable
);
以上函数具体用法参见MSDN。