等待定时器内核事件
CreateWaitableTimer(
PSECURITY_ATTRIBUTES psa,
BOOL fManualReset,
PCTSTR pszName);
进程可以获得它自己的与进程相关的现有等待定时器的句柄。
HANDLE OpenWaitableTimer(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
PCTSTR pszName);
等待定时器对象总是在未通知状态中创建,必须调用SetWaitableTimer函数来告诉定时器你想在何时让
它成为已通知态。
BOOL SetWaitableTimer(
HANDLE hTimer, //定时器
const LARGE_INTEGER *pDueTime, //pDueTime和lPeriod 一道使用,用于指明定时器何时应该第一次报时
LONG lPeriod,//指明定时器应该多长时间报时一次
PTIMERAPCROUTINE pfnCompletionRoutine,
PVOID pvArgToCompletionRoutine,
BOOL fResume);
FILETIME和LARGE_INTEGER
FILETIME 从32位的边界开始。
LARGE_INTEGER从64位边界开始。
系统移值要考虑对齐的问题。
让等待定时器给APC排队。
信标内核对象
如果当前资源数量大于0,则发出信标信号。
如果当前资源数量是0,则不发出信标信号。
系统绝不允许当前资源的数量为负值。
当前资源的数量决不能大于最大资源数量。
不要把信标的使用数量与它的当前资源数量混为一谈。
HANDLE CreateSemphore(
PSECURITY_ATTRIBUTE psa,
LONG lInitialCount,
LONG lMaximumCount,
PCTSTR pszName);
HANDLE OpenSemaphore(
DWORD fdwAccess,
BOOL bInHeritHandle,
PCTSTR pszName);
ReleaseSemaphore(
HANDLE hsem,
LONG lReleaseCount,
PLONG plPreviousCount)
信标能够以原子操作方式来执行测试和设置操作。 相当于relase 使数量+1,而成功地等待信标的副作用是它的数量递减 1
互斥对象内核对象
互斥对象包含一个使用数量,线程ID和一个递归计数器。
互斥对象比关键代码要慢(前者是内核对象)但可以跨进程
规则:
如果线程ID是0,互斥对象不被任何线程拥有,并发出该互斥对象的通知信号。
如果ID是一个非0数字,那么一个线程就拥有互斥对象,并且不发出该互斥对象的通知信号。
与所有其他内核对象不同,互斥对象在操作系统中拥有特殊的代码,允许它们违反正常规则。
HANDLE CreateMutex(
PSECURITY_ATTRIBUTES psa,
BOOL fInitialOwner,
PCTSTR pszName);
通过OpenMutex,另一个进程可以获得它自己进程与现有互斥对象相关的句柄
HANDLE OpenMutex(
DWORD fdwAccess,
BOOL bInheritHandle,
PCTSTR pszName);
fInitialOwner 控制互斥对象的初始状态,如果设为true,那么线程ID被设为调用线程ID,递归计数器被设1.
如果是false,线程ID和递归计数器都设置为0,这意味着互斥对象没有被任何线程所拥有,因此发出它的通知信号。
通过调用一个等待函数,并传递一个负责保护资源的互斥对象句柄,线程就能够获得对共享资源的访问权。
在内部,等待函数要检查线程的ID,以了解它是否是0,如果线程ID是0,那么该线程ID被设置为调用线程ID,
递归计数设置为1,同时,调用线程保持可调度状态。
如果等待函数发现ID不是0,那么调用线程进入等待状态,系统将记住这个情况,并且在互斥对象的ID重
置为0时,将线程ID设置为等待线程ID,将递归计数器设置为1,并且允许等待线程再次成为可调度线程。
检查和修改都是原子方式进行的。
特殊情况,一个线程试图等待一个未通知的互斥对象,系统查看申请线程ID和互斥对象中记录的线程ID
相同,即使互斥对象处于未通知态,系统也允许线程保持可调度状态。递归计数器加1.
BOOL RelaseMutex(HANDLE hUmtex);
递归计数器减一,当递归计数器为0,线程ID重置0,同时对象变为已通知状态。
释放的时候也要查看线程ID是否相同。
当释放对象之前,拥有互斥对象的线程被终止了,那么系统把该互斥对象视为已经被放弃,
重新初始化。
不同的是等待函数得到的返回值不是WAIT_OBJECT_0 而是,WAIT_ABANDONED.