进程是一个静态的概念。在Win32中,进程占据4GB的地址空间。一个Win32的进程并不执行指令,它只是占据着4GB的地址空间,此空间中有应用程序的代码和数据,应用程序需要的DLL也将它们的代码和数据装入到进程的地址空间。除了地址空间,进程还占据其他一些资源,比如文件、动态内存分配和线程。
为了让进程完成工作,进程必须至少占有一个线程,正是线程负责执行进程地址空间中的代码。实际上,一个进程可以包含多个线程,它们可以同时执行进程地址空间中的代码。为了做到这一点,每个线程有自己的一组CPU寄存器和堆栈。
操作系统以轮转方式向线程提供时间片,好象这些线程都在同时运行。创建一个Win32进程时,它的第一个线程称为主线程,它由系统自动生成,然后可由这个主线程生成其它的线程,这些线程又可生成更多的线程。
1 线程基础
1.1 线程函数
在启动一个线程之前,必须为线程编写一个全局的线程函数,线程函数的结构为:
#include<Windows.h>
DWORD WINAPI ThreadProc( LPVOID lpParameter )
{
……;
} // 注意ThreadProc可以是其它任意的函数名
lpParameter: Thread data passed to ThreadProc( )function using the lpParameter parameter of the CreateThread( ) function.
一般来说,C++的类成员函数不能用作线程函数。这是因为编译器会自动给类成员函数加上this指针。如果一定要以类成员函数作为线程函数,通常有以下解决方案:
1.将该成员函数声明为static类型,去掉this指针。但是带来了新的问题,那就是static成员函数只能访问static成员。解决此问题的一种方法是在调用该函数(线程函数)时将this指针作为参数传入,并在该函数体中用强制类型转换将this转换成指向该类的指针,通过该指针访问非静态成员。
2.将线程函数定义为类的友元函数。
1.2 创建线程
HANDLE CreateThread ( LPSECURITY_ATTRIBUTESlpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId )
如果创建成功则返回线程的句柄,否则返回NULL。
lpThreadAttributes是一个指向SECURITY_ATTRIBUTES结构的指针。如果使用缺省安全属性的话,可以设为NULL。
dwStackSize指定为线程分配的堆栈地址空间大小,0表示采用系统缺省值。
lpStartAddress指定线程函数。
lpParameter为传入线程函数的参数。
dwCreationFlags可以取两个值:
0:立即开始执行该线程;
CREATE_SUSPENDED:the threadis created in a suspended state, and will not run until the ResumeThread( )function is called.
lpThreadId:Pointer to a variable that receives the threadidentifier. If this parameter is NULL, the thread identifier is not returned.
1.3 挂起和继续线程
DWORD ResumeThread( HANDLE hThread )
DWORD SuspendThread( HANDLE hThread )
Each thread has a suspend count. If thesuspend count >0, the thread is suspended; otherwise, the thread is eligiblefor execution. Calling SuspendThread( ) causes the target thread's suspendcount to be incremented. The ResumeThread( ) function decrements a thread'ssuspend count. When the suspend count is decremented to zero, the execution ofthe thread is resumed.
1.4 线程优先级
BOOL SetThreadPriority ( HANDLE hThread, int nPriority )
nPriority可以是以下的值:
THREAD_PRIORITY_HIGHEST 2
THREAD_PRIORITY_ABOVE_NORMAL 1
THREAD_PRIORITY_NORMAL 0
THREAD_PRIORITY_BELOW_NORMAL -1
THREAD_PRIORITY_LOWEST -2
The GetThreadPriority( ) function retrievesthe priority of the specified thread. This value, together with the priorityclass of the thread's process, determines the thread's base-priority level.
intGetThreadPriority( HANDLE hThread )
1.5 终止线程
Terminating a thread does not necessarilyremove the thread object from the operating system. A thread object is deletedwhen the last handle to the thread is closed. The thread's termination statuschanges from STILL_ACTIVE to the value of the dwExitCode parameter.
如果要在线程内终止线程,可以调用:
VOIDExitThread( DWORD dwExitCode )
ExitThread( ) is the preferred method in C code.However, in C++ code, the thread is exited before any destructors can be calledor any other automatic cleanup can be performed. Therefore, in C++ code, youshould return from your thread function.
如果要在线程外终止线程,可以调用:
BOOLTerminateThread( HANDLE hThread, DWORD dwExitCode )
注意:该函数并不释放线程所占用的资源,一般情况下不要使用该函数。
The GetExitCodeThread( ) function retrievesthe termination status of the specified thread:
BOOL GetExitCodeThread( HANDLE hThread, LPDWORD lpExitCode )
If the specified thread has not terminated,the termination status returned is STILL_ACTIVE. If the thread has terminated,the termination status returned may be one of the following:
1.The exit value specified in the ExitThread() or TerminateThread( ) function.
2.The return value from the thread function.
3.The exit value of the thread's process.
The CloseHandle function closes an open object handle.
BOOL CloseHandle( HANDLEhObject )
1.6 线程相关函数
1.6.1 获取当前线程
HANDLE GetCurrentThread( void)
It returns a pseudo handle for the current thread.
A pseudo handle is a special constant that isinterpreted as the current thread handle. The calling thread can use thishandle to specify itself whenever a thread handle is required. Pseudo handlesare not inherited by child processes.
GetCurrentThread( ) can not create a handle that canbe used by other threads to refer to the calling thread. A thread can create areal handle to itself that can be used by other threads, or that can beinherited by child processes, by specifying the pseudo handle as the sourcehandle in a call to the DuplicateHandle( ). A thread can also use the OpenThread() to open a real handle to itself.
The pseudo handle need not be closed when it is nolonger needed. Calling the CloseHandle( ) with pseudo handle has no effect. Ifthe pseudo handle is duplicated by DuplicateHandle( ), the duplicate handlemust be closed.
1.6.2 获取当前线程的ID
DWORD GetCurrentThreadId( void)
1.6.3 获取指定线程的ID
DWORD GetThreadId( HANDLEThread )
1.6.4 打开指定的线程
HANDLE OpenThread( DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwThreadId )
dwDesiredAccess: The access rights for thread includeDELETE, WRITE_DAC, WRITE_OWNER THREAD_ALL_ACCESS and READ_CONTROL.
SYNCHRONIZE |
Enable the thread handle in any of the wait functions. |
THREAD_GET_CONTEXT |
Read the context of a thread using GetThreadContext( ) |
THREAD_SET_CONTEXT |
Write the context of a thread using SetThreadContext( ) |
THREAD_SUSPEND_RESUME |
Suspend or Resume a thread |
THREAD_TERMINATE |
Terminate a thread using TerminateThread |
THREAD_QUERY_INFORMATION |
Read certain information from the thread object |
THREAD_SET_INFORMATION |
Set certain information in the thread object |
bInheritHandle: If TRUE, new process inherits the handle.If FALSE, the handle is not inherited.
1.6.5 将当前线程挂起指定的秒数
VOID Sleep( DWORDdwMilliseconds )
DWORD SleepEx( DWORDdwMilliseconds, BOOL bAlertable )
dwMilliseconds: A value of zero causes the thread torelinquish the remainder of its time slice to any other thread of equalpriority that is ready to run. If there are no other threads of equal priorityready to run, the function returns immediately, and the thread continuesexecution.
A value of INFINITE indicates that the suspensionshould not time out.
The SleepEx( ) suspends the current thread until thespecified condition is met. Execution resumes whens one of the followingoccurs:
1.An I/O completion callback function iscalled
2.An asynchronous procedure call (APC) isqueued to the thread
3.The minimum time-out interval elapses
bAlertable: If FALSE, SleepEx( ) does not return untilthe time-out period has elapsed. If TRUE and the calling thread has called theextended I/O function, ReadFileEx( ) or WriteFileEx( ), SleepEx( ) returns wheneither the time-out period has elapsed or when an I/O completion callbackfunction occurs. If an I/O completion callback occurs, the I/O completionfunction is called. If an APC is queued to the thread, QueueUserAPC( ), SleepEx() returns when either the timer-out period has elapsed or when the APC functionis called.
1.6.6 线程间的切换
BOOL SwitchToThread(void);
SwitchToThread( ) causes the calling thread to yieldexecution to another thread that is ready to run on the current processor. Theoperating system selects the thread to yield to.
If SwitchToThread( ) causes the operating system toswitch execution to another thread, the return value is nonzero. If there areno other threads ready to execute, the operating system does not switchexecution to another thread, and the return value is zero.
To uses SwitchToThread( ), define _WIN32_WINNT as0x0400 or later.
2 进程基础
2.1 进程的创建
BOOL CreateProcess( LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation );
lpApplicationName: It specifies the full path and file name ofthe module to execute or it can specify a partial name. In the case of a partialname, CreateProcess( ) uses the current directory to complete thespecification. If the file name does not contain an extension, .exe is assumed.
lpCommandLine: It specifies the command line to execute. Itcan be NULL. In that case, CreateProcess( ) uses the string pointed to bylpApplicationName as the command line.
If lpApplicationName is NULL, the first white-spacedelimited token in the command line specifies the module name. If you are usinga long file name that contains a space, use quoted strings to indicate wherethe file name ends and the arguments begin. For example:
CreateProcess( NULL, "\"C:\\Program Files\\SubDir\\MyApp.exe\" -t -s", ……)
If the file name does not contain an extension, .exeis appended.
If the file name ends in . with no extension, or if the file name contains a path, .exe isnot appended.
If the file name does not contain a directory path,the system searches for the executable file in the following sequence:
1.The directory from which the applicationloaded.
2.The current directory for the parentprocess.
3.The 32-bit Windows system directory. UseGetSystemDirectory( ) to get this directory.
4.The Windows directory. UseGetWindowsDirectory( ) to get this directory.
5.The directories that are listed in the PATHenvironment variable.
The system adds a null character to the command linestring to separate the file name from the arguments. This divides the originalstring into two strings for internal processing.
lpProcessAttributes: If NULL, the handle can not be inherited bychild processes.
lpThreadAttributes: If NULL, the handle can not be inherited bychild processes.
bInheritHandles: If TRUE, each inheritable handle in thecalling process is inherited by the new process. If FALSE, the handles are notinherited.
dwCreationFlags: Flags that control the priority class andthe creation of the process. Flags can be specified in any combination.
CREATE_DEFAULT_ERROR_MODE |
The new process does not inherit the error mode of the calling process (the default), instead gets the default error mode. |
CREATE_NEW_CONSOLE |
The new process has a new console, instead of inheriting its parent's console (the default). This flag can not be used with CREATE_NO_WINDOW or DETACHED_PROCESS. |
CREATE_NO_WINDOW |
The process is a console application that is run without a console window. This flag is valid only when starting a console application. This flag can not be used with CREATE_NEW_CONSOLE or DETACHED_PROCESS or when starting DOS-based application. |
CREATE_SUSPENDED |
The primary thread of the new process is created in a suspended state, and does not run until the ResumeThread function is called. |
CREATE_UNICODE_ENVIRONMENT |
If this flag is set, the environment block pointed to by lpEnvironment uses Unicode. Otherwise, uses ANSI. |
DETACHED_PROCESS |
For console processes, the new process does not inherit its parent's console (the default) and can call the AllocConsole( ) at a later time to create a new console. It can not be used with CREATE_NEW_CONSOLE and CREATE_NO_WINDOW. |
lpEnvironment: If NULL, the new process uses the environmentof the calling process. An environment block consists of a null-terminatedblock of null-terminated strings. Each string is in the form: name=value.
A ANSI environment block is terminated by two zerobytes: one for the last string, one more to terminate the block.
A Unicode environment block is terminated by four zerobytes: two for the last string, two more to terminate the block.
lpCurrentDirectory: It specifies the full path to the currentdirectory for the process. If NULL, the new process will have the same currentdirectory as the calling process.
2.2 进程的结束
VOID ExitProcess( UINTuExitCode )
All of the object handles opened by the process areclosed.
All of the threads in the process, except the callingthread, terminate their execution.
The state of the process object becomes signaled,satisfying any threads that had been waiting for the process to terminate.
The states of all threads of the process becomesignaled, satisfying any threads that had been waiting for the threads toterminate.
The termination status of the process changes fromSTILL_ACTIVE to the exit value of the process.
Exiting a process does not cause child processes to beterminated.
Exiting a process does not necessarily remove theprocess object from the operating system. A process object is deleted when thelast handle to the process is closed.
The preferred way to shut down a process is by usingthe ExitProcess( ), because ExitProcess( ) sends notification of approachingtermination to all DLLs attached to the process. Other means of shutting down aprocess do not notify the attached DLLs. Note that when a thread callsExitProcess( ), other threads of the process are terminated without anopportunity to execute any additional code, including the thread terminationcode of attached DLLs.
BOOL TerminateProcess( HANDLEhProcess, UINT uExitCode )
TerminateProcess( ) terminates the specified processand all of its threads. TerminateProcess( ) stops execution of all threadswithin the process and requests cancellation of all pending I/O. The terminatedprocess can not exit until all pending I/O has been completed or canceled.
2.3 设置线程的优先级
BOOL SetPriorityClass( HANDLEhProcess, DWORD dwPriorityClass )
dwPriorityClass: REALTIME_PRIORITY_CLASS
HIGH_PRIORITY_CLASS
ABOVE_NORMAL_PRIORITY_CLASS
NORMAL_PRIORITY_CLASS
BELOW_NORMAL_PRIORITY_CLASS
IDLE_PRIORITY_CLASS
DWORD GetPriorityClass(HANDLE hProcess )
2.4 进程相关函数
2.4.1 获取当前进程
HANDLE GetCurrentProcess( void)
A pseudo handle is a special constant that isinterpreted as the current process handle. The calling process can use a pseudohandle to specify its own process whenever a process handle is required. Pseudohandles are not inherited by child processes.
A process can create a real handle to itself that isvalid in the context of other processes, or that can be inherited by childprocesses, by specifying the pseudo handle as the source handle in a call tothe DuplicateHandle( ). A process can also use the OpenProcess( ) to open areal handle to itself.
The pseudo handle need not be closed when it is nolonger needed. Calling the CloseHandle( ) with a pseudo handle has no effect.If the pseudo handle is duplicated by DuplicateHandle( ), the duplicate handlemust be closed.
2.4.2 获取当前进程的ID
DWORD GetCurrentProcessId( void)
2.4.3 获取当前进程的ExitCode
BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode )
If the specified process has not terminated, the terminationstatus returned is STILL_ACTIVE.
If the process has terminated, the termination statusreturned may be one of the following:
1.The exit value specified in the ExitProcess() or TerminateProcess( )
2.The return value from the main( ) or WinMain() of the process.
3.The exception value for an unhandledexception that caused the process to terminate
2.4.4 获取进程的句柄数目
BOOL GetProcessHandleCount(HANDLE hProcess, PDWORD pdwHandleCount )
To usesGetProcessHandleCount(), define _WIN32_WINNT as 0x0501 or later.
2.4.5 获取指定进程的ID
DWORD GetProcessId( HANDLEProcess )
2.4.6 获取指定线程的进程ID
DWORD GetProcessIdOfThread(HANDLE Thread )
2.4.7 打开进程
HANDLE OpenProcess( DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId )
bInheritHandle: If TRUE, the handle is inheritable. IfFALSE, the handle can not be inherited.
3 线程/进程同步
DWORDWaitForSingleObject( HANDLE hHandle,DWORDdwMilliseconds )
It can wait for the following objects: Event Mutex Semaphore Job
Process Thread Waitable timer
If dwMilliseconds=0,WaitForSingleObject( ) tests the object's state and returns immediately.
If dwMilliseconds=INFINITE, WaitForSingleObject( )'stime-out interval never elapses.
If WaitForSingleObject( ) succeeds, thereturn value can be one of the following values:
WAIT_ABANDONED
The specified object is a mutex object thatwas not released by the owning thread before the owning thread terminated, inanother words, the mutex object was abandoned. Ownership of the mutex object isgranted to the calling thread, and the mutex is set to non-signaled.
WAIT_OBJECT_0
The state of the specified object issignaled.
WAIT_TIMEOUT
The time-out interval elapsed, and theobject's state is non-signaled.
If WaitForSingleObject( ) fails, the returnvalue is WAIT_FAILED.
DWORDWaitForMultipleObject( DWORD nCount,
CONST HANDLE *lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds )
It can wait for the following objects: Event Mutex Semaphore Job
Process Thread Waitable timer
nCount:Number of object handles in the array pointed to bylpHandles.
lpHandles:Pointer to an array of object handles. The array cancontain handles to objects of different types. It can not contain the multiplecopies of the same handle.
bWaitAll:If TRUE, the function returns when the state of allobjects in the lpHandles array is signaled. If FALSE, the function returns whenthe state of any one of the objects is set to signaled.
If the function succeeds, the return valuecan be one of the following values:
WAIT_ABANDONED_0 to WAIT_ABANDONED_0+nCount–1
If bWaitAll is TRUE, the return valueindicates that the state of all specified objects is signaled and at least oneof the objects is an abandoned mutex object.
If bWaitAll is FALSE, the return valueminus WAIT_ABANDONED_0 indicates the index of an mutex object that was abandoned.
WAIT_OBJECT_0 to WAIT_OBJECT_0+nCount–1
If bWaitAll is TRUE, the return valueindicates that the state of all specified objects is signaled.
If bWaitAll is FALSE, the return valueminus WAIT_OBJECT_0 indicates the index of the object that was signaled. Ifmultiple objects become signaled, the return value minus WAIT_OBJECT_0indicates the index of the first object that was signaled.
WAIT_TIMEOUT
The time-out interval elapsed and theconditions are not satisfied.
If the function fails, the return value isWAIT_FAILED.
3.1 Mutex(内核对象)
Mutex对象在同一时刻只能被一个线程占用。
3.1.1 创建Mutex
HANDLE CreateMutex( LPSECURITY_ATTRIBUTESlpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName )
bInitialOwner:If TRUE, the calling thread obtains initial ownershipof the mutex object. Otherwise, the calling thread does not obtain ownership ofthe mutex.
lpName:Specify the name of the mutex object. If NULL, the mutexobject is created without name.
The handle returned by CreateMutex( ) hasthe MUTEX_ALL_ACCESS access right.
3.1.2 多进程间Mutex的使用
Multiple processes can have handles of thesame mutex object for inter-process synchronization. The following object-sharingmechanisms are available:
1.A childprocess created by the CreateProcess( ) function can inherit a handle of amutex object if the lpMutexAttributes parameter of CreateMutex( ) enabledinheritance.
2.A processcan specify the mutex-object handle in the DuplicateHandle( ) function.
3.A processcan specify the name of a mutex object in the OpenMutex( )/CreateMutex( )function.
HANDLE OpenMutex( DWORDdwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName )
dwDesiredAccess:Access to the mutex object,可以取以下值:
DELETE The right to delete the object.
READ_CONTROL The rightto read the information in the object's security descriptor.
SYNCHRONIZE Theright to use the object for synchronization. This enables a thread to waituntil the object is in the signaled state.
WRITE_OWNER The right to change the owner in theobject's security descriptor.
MUTEX_ALL_ACCESS All access rights.
MUTEX_MODIFY_STATE Modify state access,required for the ReleaseMutex( ).
bInheritHandle:If TRUE, process created by the CreateProcess( ) caninherit the handle; otherwise, the handle can not be inherited.
3.1.3 释放Mutex
BOOL ReleaseMutex( HANDLE hMutex )
3.1.4 清除Mutex
BOOL CloseHandle( HANDLE hObject )
3.2 Semaphore(内核对象)
Semaphore对象在创建时指定可以同时占用它的最大线程数。
HANDLECreateSemaphore( LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName )
The handle returned by CreateSemaphore( )has the SEMAPHORE_ALL_ACCESS accessright.
HANDLEOpenSemaphore( DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName )
dwDesiredAccess可以取以下值:
SEMAPHORE_ALL_ACCESS All possible access rights.
SEMAPHORE_MODIFY_STATE Modify state access, required for the ReleaseSemaphore().
BOOLReleaseSemaphore( HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount )
lReleaseCount:If lReleaseCount would cause the semaphore's count toexceed the lMaximumCount, the count is not changed and returns FALSE.
BOOLCloseHandle( HANDLE hObject )
3.3 Event(内核对象)
Event对象只有两种状态,signaled状态和non-signaled状态。
创建Event对象:
HANDLECreateEvent( LPSECURITY_ATTRIBUTESlpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName )
bManualReset:If TRUE, when an event object is signaled, it remainssignaled until it is explicitly reset to non-signaled by the ResetEvent( ). IfFALSE, when an event object is signaled, it remains signaled until a waitingthread is released; the system then automatically resets the state to non-signaled.
bInitialState:If TRUE, the initial state of the event object issignaled; otherwise, it is non-signaled.
The handle returned by CreateEvent( ) hasthe EVENT_ALL_ACCESS access right.
HANDLEOpenEvent( DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName )
dwDesiredAccess可以取以下值:
EVENT_ALL_ACCESS Allpossible access rights for an event object.
EVENT_MODIFY_STATE Modify state access,required for SetEvent( ) and ResetEvent( ).
The ResetEvent( ) sets the specified event objectto non-signaled state:
BOOL ResetEvent ( HANDLEhEvent )
The SetEvent( ) sets the specified eventobject to the signaled state.:
BOOLSetEvent( HANDLE hEvent )
BOOLCloseHandle( HANDLE hObject )
3.4 WaitableTimer(内核对象)
WaitableTimer对象是在某个时间或按规定的时间间隔发出自己信号的内核对象。
To uses WaitableTimer, define _WIN32_WINNTas 0x0400 or later.
创建WaitableTimer对象:
HANDLECreateWaitableTimer( LPSECURITY_ATTRIBUTESlpTimerAttributes,
BOOL bManualReset,
LPCTSTR lpTimerName )
bManualReset:If TRUE, when a timer is signaled, it remains in signaleduntil it is explicitly reset to non-signaled by SetWaitableTimer( ). If FALSE, whena timer is signaled, it remains signaled until a waiting thread is released;the system then automatically resets the state to non-signaled.
Timers are initially inactive. To activatea timer, call SetWaitableTimer( ). If the timer is already active when you callSetWaitableTimer( ), the timer is reactivated:
BOOLSetWaitableTimer( HANDLE hTimer,
const LARGE_INTEGER*pDueTime,
LONG lPeriod,
PTIMERAPCROUTINE pfnCompletionRoutine,
LPVOID lPvArgToCompletionRoutine,
BOOL fResume )
pDueTime:Time after which the timer is signaled, in 100 nano-seconds.Negative values indicate relative time. Positive values indicate absolute time.Be sure to use a UTC-based absolute time, as the system uses UTC-based timeinternally.
lPeriod:Period of the timer, in milliseconds. If zero, thetimer is signaled once. If greater than zero, the timer is periodic. A periodictimer automatically reactivates each time the period elapses, until the timeris canceled using the CancelWaitableTimer( ) or reset using SetWaitableTimer( ).If less than zero, the function fails.
pfnCompletionRoutine:Pointer to an completion routine executed when thetimer is signaled.
lpArgToCompletionRoutine:Pointer to a structure that is passed to thecompletion routine.
fResume:If TRUE, a system is restored in suspended powerconservation mode when the timer state is set to signaled. Otherwise, thesystem is not restored.
When the specified due time arrives:
1.the timer becomes inactive;
2.the state of the timer is set to signaled;
3.the timer is reactivated using thespecified period;
4.the thread that set the timer calls the completionroutine。
VOIDCALLBACK TimerProc( LPVOIDlpArgToCompletionRoutine,
DWORD dwTimerLowValue,
DWORD dwTimerHighValue );
lpArgToCompletionRoutine:Pointer to a parameter that is passed to the TimerProc() through the lpArgToCompletionRoutine parameter of the SetWaitableTimer( )function.
dwTimerLowValue:Low-order portion of the UTC-based time at which thetimer was signaled.
dwTimerHighValue:High-order portion of the UTC-based time at which thetimer was signaled.
HANDLEOpenWaitableTimer ( DWORD fdwAccess,
BOOL bInherithandle,
PCTSTR pszName )
fdwAccess可以取以下值:
TIMER_ALL_ACCESS All possibleaccess rights for a waitable timer object.
TIMER_MODIFY_STATE Modify state access,required for the SetWaitableTimer( ) and
CancelWaitableTimer( )functions.
The CancelWaitableTimer( ) inactivate the waitabletimer, it does not change the state of the timer:
BOOlCancel WaitableTimer( HANDLE hTimer)
BOOLCloseHandle( HANDLE hObject )
3.5 CriticalSection(用户对象)
Mutex,Semaphore,Event和WaitableTimer都需要函数wait()的支持才能够完成线程的同步,而CriticalSection就不需要函数wait( )的支持。一般在需要同步的代码之前添加EnterCriticalSection( )或TryEnterCriticalSection( ),之后添加LeaveCriticalSection( )就可完成线程的同步。
通常情况下,CriticalSection被定义为全局变量,并进行初始化:
CRITICAL_SECTION gCriticalSection;
voidInitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
The EnterCriticalSection( )/TryEnterCriticalSection() returns when the calling thread is granted ownership of the specifiedcritical section object. The difference is that TryEnterCriticalSection( )returns immediately, regardless of whether it obtained ownership of thecritical section, while EnterCriticalSection( ) blocks until the thread cantake ownership of the critical section:
voidEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
BOOLTryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
After a thread has ownership of a criticalsection, it can make additional calls to EnterCriticalSection( ) orTryEnterCriticalSection( ). A thread must call LeaveCriticalSection( ) once foreach time that it entered the critical section.
voidLeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
Any thread of the process can use theDeleteCriticalSection( ) to release the system resources which were allocated forthe critical section object. After DeleteCriticalSection( ) has been called,the critical section object can no longer be used:
voidDeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
Mutex与CriticalSection功能相同,但是Mutex属于内核对象,而CriticalSection属于用户对象,导致二者有如下不同:
1.Mutex的速度比CriticalSection慢
2.不同进程中的线程能够访问同一个Mutex