关于若干Win32多线程函数API详解

来源:互联网 发布:sql中order by的用法 编辑:程序博客网 时间:2024/06/03 01:55

关于若干Win32多线程函数API详解

 

CreateThread

函数功能:该函数创建一个在调用进程的地址空间中执行的线程。

函数原型: 

HANDLE  CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes,

DWORD dwStackSize,  LPTHREAD_START_ROUTINE  lpStartAddress, 

LPVOID  lpParameterDWORD dwCreationFlags,  LPDWORD lpThreadld);

参数:

lpThreadAttributes指向——个SECURITY_ATTRIBUTES结构,该结构决定了返回的句柄是否可被子进程继承。若lpThreadAttributesNULL,则句柄不能被继承。

    Windows NT中该结构的lpSecurityDescriptor成员定义了新进程的安全性描述符。若lpThreadAttributesNULL,则线程获得一个缺省的安全性描述符。

dwStackSize定义原始堆栈提交时的大小(按字节计)。系统将该值舍入为最近的页。若该值为0,或小于缺省时提交的大小,缺省情况是使用与调用线程同样的大小。更多的信息,请看线程堆栈大小。

lpStarAddress指向一个LPTHREAD_START_ROUTINE类型的应用定义的函数,该线程执行此函数。该指针还表示远程进程中线程的起始地址。该函数必须存在于远程进程中。

lpParameter定义一个传递给该进程的32位值。

dwCreationFlags定义控制进程创建的附加标志。若定义了CREATE_SUSPENDED标志,线程创建时处于挂起状态,并且直到ResumeThread函数调用时才能运行。若该值为0,则该线程在创建后立即执行。

lpThreadld指向一个32位值,它接受该线程的标识符。

返回值:

若函数调用成功,返回值为新线程的句柄;若函数调用失败,返回值为NULL

备注:

新进程的句柄创建时设为THREAD_ALL_ACESS访问权限。若未提供安全性描述符,则该句柄可被任何要求一个线程对象句柄的函数所使用。若提供了安全性描述符,则以后使用该句柄时,将在授权访问以前执行访问检查。若访问检查拒绝访问,则请求进程不能使用该句柄获得对该线程的访问。

    线程从lpStartAddress参数定义的函数处开始执行。若该函数返回,则DWORD返回值被用于以隐含调用ExitThread函数的方法终止该线程。使用GetExitCodeThread函数来获得线程的返回值。

    CreateRemoteThread函数使得一个新的执行线程从指定进程的地址空间开始执行。该线程可以访问进程打开的所有对象。

新线程的句柄创建时对于新线程具有完全访问的权限。若未提供安全性描述符,则任何一个需要线

程对象句柄的函数均可使用该句柄。若提供了一个安全性描述符,则以后使用该句柄时,将在授权访问

以前执行访问检查。若访问检查拒绝访问,则请求进程不能使用该句柄获得对该线程的访问。

    即使lpStartAddress指向数据,代码,或不可访问,CreateRemoteThread函数仍能成功调用。若线程运行时起始地址无效,则发生异常,线程终止。由于无效的起始地址而终止的线程被处理为“从该线程的进程中错误退出”。此种行为类似于CreateProcess的异步特性。在CreateProcess函数中,即使进程引用了无效的或己丢失的动态连接库(DLL)仍能被创建。

线程创建时拥有THREAD_PRIORITY_NORMAL优先权。使用GetThreadPrioritySetThreadPriority函数可以获得和设置线程的优先权值。

    —个线程终止时,该线程对象被设为发信号状态,以满足在该对象上等待的所有进程。

    一个线程对象始终存在于系统中,直到该线程终止,且它所有的句柄都已通过调用CloseHandle函数关闭。

    ExitProcess,ExitThread,CreateThread,CreateRemoteThread和一个正被启动(调用CreateProcess的结果)的进程将被在进程内部彼此串联起来。任一时刻,在某一地址空间中仅能发生上述事件之一。这意味着将有如下的限制:

l            在进程启动和DLL初始化例程期间,可以创建新线程,但是新线程只有在进程的DLL初始化完成后才开始执行。

l            任一时刻,进程中仅有一个线程可以存在于一个DLL初始化例程或一个分离例程中。

l            仅当所有线程的DLL初始化例程和分离例程都已完成时,ExitProcess函数才返回。

    使用C运行时间库函数的线程应当使用C运行时间函数来进行线程管理,而不是使用CreateThreadExitThread函数。若不这样做,调用ExitThread函数时将导致少量内存泄漏。

   

ExitThread

函数功能:该函数结束一个线程。

函数原型:

VOID ExitThread(  DWORD dwExitCode );

参数:

dwExitCode定义调用线程的退出代码。使用GetExitCodeThread函数来检取一个线程的退出代码。

返回值:无。

备注:

调用ExitThread函数,是结束一个线程的较好的方法。调用该函数后(或者直接地调用,或者从一个线程过程返回),当前线程的堆栈去配线程终止。所有附加动态连接库(DLL)的入口点函数被激活,激活值表明该线程正从DLL脱离。若调用该函数时,该线程为进程的最后一个线程,则该线程的进程也被终止。

线程对象的状态变为发信号状态,以释放所有正在等待该线程终止的其他线程。线程的终止状态从STILL_ACTIVATE变为dwExitCode参数的值。

线程结束时不必从操作系统中移去该线程对象。当线程的最后一个句柄关闭时,该线程对象被删除。

ExitProcessExitThreadCreateThreadCreateRemoteThread和一个正被启动(调用CreateProcess的结果)的进程将被在进程内部被此串联起来。任一时刻,在某一地址空间中仅能发生上述事件之一。这意味着将有如下的限制:

l            在进程启动和DLL初始化例程期间,可以创建新线程,但是新线程只有在进程的DLL初始化完成后才开始行。

l            任一时刻,进程中仅有一个线程可以存在于一个DLL初始化例程或一个分离例程中。

l            仅当所有线程的DLL初始化例程和分离例程都己完成时,ExitProcess函数才返回。

使用C运行时间库函数的线程应当使用C运行时间函数来进行线程管理,而不是使用CreateThreadExitThread函数。若不这样做,调用ExitThread函数时将导致少量内存泄漏。

   

Sleep

函数功能:该函数对于指定的时间间隔挂起当前的执行线程。

函数原型:VOID Sleep(DWORD dwMilliseconds)

参数:

dwMilliseconds定义挂起执行线程的时间,以毫秒为单位。取值为0时,该线程将余下的时间片交给处于就绪状态的同一优先级的其他线程。若没有处于就绪状态的同一优先级的其他线程,则函数立即返回,该线程继续执行。若取值为INFINITE则造成无限延迟。

返回值:该函数没有返回值。

备注:一个线程可以在调用该函数时将睡眠时间设为0毫秒,以将剩余的时间片交出。

    使用Sleep函数和直接或间接创建窗口的代码时必须非常小心。若线程创建了窗口,它就必须处理消息。消息广播被发送给系统中的所有窗口。若有一个线程调用Sleep函数时使用了无限延迟,则系统会死锁。两个直接创建窗口的代码的例子是DDECOM CoInitialize。因此,若有一个创建窗口的线程,则使用MsgWaitForMutipleObjectsMsgWaitForMutipleObjectsEx函数,而不使用Sleep函数。

 

CreateMutex

函数功能:该函数是创建有名或者无名的互斥对象。

函数原型:

HANDLE CreateMutex(  LPSECURITY_ATTRIBUTES lpMutexAttributes

BOOL bInitialOwner, LPCTSTR lpName  )

参数:

lpMutexAttributes指向SECURITY_ATTRIBUTES结构的指针,该结构决定子进程是否能继承返回句柄。如果lpMutexAttributesNULL,那么句柄不能被继承。

    Windows NT中该结构的lpSecurityDescriptor成员指定新互斥对象的安全描述符。如果lpMutexAttributesNULL,那么互斥对象获得缺省的安全描述符。

bInitialOwner指定互斥对象的初始所属身份。如果该值为TRUE并且调用者创建互斥对象,那么调用线程获得互斥对象所属身份。否则,调用线程不能获得互斥对象所属身份。判断调用者是否创建互斥对象请参阅返回值部分。

lpName指向以NULL结尾的字符串,该字符串指定了互斥对象名。该名字的长度小于MAX_PATH且可以包含除反斜线路径分隔符( / )以外的任何字符。名字是区分大小写的。

    如果lpName与已存在的有名互斥对象名相匹配,那么该函数要求用MUTEX_ALL_ACCESS权限访问已存在的对象。在这种情况下,由于参数bInitialOwner己被创建进程所设置,该参数被忽略。如果参数lpMutexAttributes不为NULL,它决定句柄是否解除继承,但是其安全描述符成员被忽略。

    如果lpNameNULL,那么创建的互斥对象无名。

    如果lpName与已存在的事件、信号量、可等待定时器、作业、或者文件映射对象的名字相匹配,那么函数调用失败,并且GetLastError函数返回ERPOR_INVALID_HANDLE。其原因是这些对象共享相同的名字空间。

返回值:

如果函数调用成功,返回值是互斥对象句柄;如果函数调用之前,有名互斥对象已存在,那么函数给已存在的对象返回一个句柄,并且函数GetLastError返回ERROR_ALREADY_EXISTS,否则,调用者创建互斥对象。

如果函数调用失败,则返回值为NULL。若想获得更多错误信息,请调用GetLastError函数。

备注:

由函数CreateMutex返回的句柄有MUTEX_ALL_ACCESS权限可以去访问新的互斥对象,并且可用在要求互斥对象句柄的任何函数中。

    调用进程中的任何线程可以在调用等待函数时指定互斥对象句柄。当指定对象的状态为信号态时,返回单对象等待函数。当任何一个或者所有的互斥对象为信号态时,返回多对象等待函数被指令。等待函数返回后,等待的线程被释放继续向下执行。

    当一个互斥对象不被任何线程拥有时,处于信号态。创建该对象的线程可以使用bInitialOwner标志来请求立即获得对该互斥对象的拥有权。否则,线程必须使用等待函数来请求拥有权。当互斥对象处于信号态,等待的线程获得对该对象的拥有权时,此互斥对象的状态被设置为非信号态,等待函数返回。任意时刻,仅有一个线程能拥有该互斥对象,线程可以使用ReleaseMutex函数来释放对这个互斥对象的拥有权。   

若线程已经拥有了一个互斥对象,那么它可以重复调用等待函数而不会发生阻塞,一般情况下,用户不会重复等待同一个互斥对象,但是这种机制防止了线程因等待它已经拥有的互斥对象而发生死锁。然而,线程必须为每一次等待调用一次ReleaseMutex函数来释放该互斥对象。

    两个或多个进程可以调用CreateMutex来创建同名的互斥对象,第一个进程实际创建互斥对象,以后的进程打开已存在的互斥对象的句柄。这使得多个进程可以得到同一个互斥对象的句柄,从而减轻了用户的负担,使用户不必判断创建进程是否为第一个启动的进程。使用这种技术时,应该把bInitialOwner标志设为FALSE;否则很难确定开始时哪一个进程拥有该互斥对象。

    由于多进程能够拥有相同互斥对象的句柄,通过使用这个对象,可使多进程同步。以下为共亨对象机制:

    如果CreateMutex中的lpMutexAttributes参数允许继承,由CreateProcess函数创建的子进程可以继承父进程的互斥对象句柄。

    一个进程可以在调用DuplicateHandle函数时指定互斥对象句柄来创建一个可以被其他进程使用的双重句柄。一个进程在调用OpenMutexCreateMutex函数时能指定互斥对象名。

    使用CloseHandle函数关闭句柄,进程结束时系统自动关闭句柄。当最后一个句柄被关闭时,互斥对象被销毁。

   

ReleaseMutex

函数功能:该函数放弃指定互斥对象的拥有权。

函数原型:BOOL ReleaseMutex(HANDLE hMutex)

参数:

hMutex互斥对象句柄。为CreateMutexOpenMutex函数的返回值。

返回值:

如果函数调用成功,那么返回值是非零值;如果函数调用失败,那么返回值是零值。若想获得更多错误信息,请调用GetLastError函数。

备注:

如果调用线程不拥有互斥对象,ReleaseMutex函数失败。

    一个线程通过调用等待函数拥有互斥对象。创建该互斥对象的线程也拥有互斥对象,而不需要调用等待函数。当互斥对象的所有者线程不再需要互斥对象时,它可以调用ReleaseMutex函数。

    当一个线程拥有一个互斥对象后,它可以用该互斥对象多次调用等待函数而不会阻塞。这防止一个线程等待一个它已拥有的互斥对象时出现死锁。不过,为了释放所有权,该线程必须为每一个等待操作调用一次ReleaseMutex函数。

 

WaitForSingleObject

函数功能:当如下情况之一发生时该函数返回:指定对象处于信号态;超时。

函数原型: 

DWORD  WaitForSingleObject(  HANDLE hHandleDWORD dwMilliseconds)

参数:

hHandle等待对象句柄。若想了解指定句柄的对象类型列表,参阅下面说明部分。

    WndowsNT中,句柄必须有SYNCHRONIZE访问权限。若想获得更多的信息,请查看Standard Access Rights

dwMilliseconds指定以毫秒为单位的超时间隔。如果超时,即使对象的状态是非信号态的并且没有完成,函数也返回。如果dwMilliseconds0,函数测试对象的状态并立刻返回:如果dwMillsecondsINFINlTE,函数从不超时。

返回值:

如果函数调用成功,返回值表明引起函数返回的事件。可能值如下:

l            WAIT_ABANDONED:指定对象是互斥对象,在线程被终止前,线程没有释放互斥对象。互斥对象的所属关系被授予调用线程,并且该互斥对象被置为非信号态。

l            WAIT_OBJECT_0:指定对象的状态被置为信号态。

l            WAlT_TIMEOUT:超时,并且对象的状态为非信号态。

    如果函数调用失败,返回值是WAIT_FAILED。若想获得更多错误信息,请调用GetLastError函数。

备注:

WaitForSingleObjects函数决定等待条件是否被满足。如果等待条件并没有被满足,调用线程进入一个高效的等待状态,当等待满足条件时占用非常少的处理器时间。

    在运行前,一个等待函数修改同步对象类型的状态。修改仅发生在引起函数返回的对象身上。例如信号的计数减1

    WaitForSingleObject函数能等待如下对象:

    Change notification(改变通告)Console input(控制台输入)Event(事件)Job(作业);

    Mutex  (互斥对象)Process  (进程)Semaphore  (信号量)Thread  (线程)

    Waitable timer  (可等待定时器)

    当使用等待函数或代码直接或间接创建窗口时,一定要小心。如果一个线程创建了任何窗口,它必须处理进程消息。消息广播被发送到系统的所有窗口。一个线程用没有超时的等待函数也许会引起系统死锁。间接创建窗口的两个例子是DDECOM CoInitialize。因此,如果用户有一个创建窗口的线程,用MsgWaitForMultipleObjectsMsgWaitForMultipleObjectsEx函数,而不要用SignalObjectAndWait函数。

 

WaitForMultipleObjects

函数功能:  WaiForMultipleObjects函数当下面条件之一满足时。返回任意一个或全部:指定对象处于信号态;超时间隔已过。

函数原型:  DWORD WaitForMultipleObjects(DWORD nCountCONST HANDLE *lpHandlesBOOL fWaitAllDWORD dwMilliSeconds)

参数:

nCount  指定由  1pHandles所指向的数组中的句柄对象数目最大对象句柄数目MAXIMUM_WAIT_OBJECTS

lpHandles指向对象句柄数组的指针。若想了解指定句柄的对象类型列表,参阅下面说明部分。该数组可以包含不同类型对象的勾柄。

    WindowsNT中,该句柄必须有SYNCHRONIZE访问权限。若想获得更多的信息,请查看Standard Access Rights

    Windows 95中,由DuplicateHandIe函数所创建的其他句柄不能被复制。

fWaitAll指定等待类型。如果为TRUE,当lpHandles指向的数组里的全部对象为信号态时,函数返回。如果为FALSE,函数当由lpHandles指向的数组里的任一对象为信号态时,函数返回。对于后者,返回值表明那个对象引起函数返回。

dwMilliseconds指定以毫秒为单位的超时间隔。如果超时,即使bWaitAll参数指定的条件没有满足,函数也返回。如果dwMilliseconds0,函数测试指定对象的状态并立刻返回。如果dwMillisecondsINFINITE,函数从不超时。

返回值:

如果函数调用成功,返回值表明引起函数返回的事件。可能值如下:

    WAIT_OBJECT_0(WAITOBJECT_0+nCount-1)  如果bWaitAllTRUE,那么返回值表明所有指定对象的状态为信号态。如果bWaitAllFALSE,那么返回值减去WAIT_OBJECT_0表明引起函数返回的的对象的pHandles数组索引。如果多于一个对象变为信号态,则返回的是数组索引最小的信号态对象索引。

    WAIT_ABANDONED_0(WAIT_ABANDONED_0nCount1):如果bWaitAllTRUE,那么返回值表明所有指定对象的状态为信号态,并且至少一个对象是己放弃的互斥对象。如果bWaitAllFALSE,那么返回值减去WAIT_ABANDONED_0表明引起函数返回的放弃互斥对象的pHandles数组索引。

    WAIT_TIMEOUT  超时并且由参数bWaitAll指定的条件没有满足。

如果函数调用失败,返回值是WAIT_FAILED。若想获得更多错误信息,请调用GetLastErro r函数。

 

CreatSemapore

函数功能:该函数是创建一个有名或者无名信号对象。

函数原型:

HANDLE CreateSemaphore(

     LPSECURITY_ATTRIBUTES lpAttributes,

     LONG lInitialCount,

     LONG lMaximumCount,

    LPCTSTR lpName

);

参数:

lpAttributes             安全属性。如果是NULL就表示要使用默认属性。

lInitialCount           semaphore的初值。必须大于或等于0,并且小于或等于lMaximumCount

lMaximumCount     Semaphore的最大值。这也就是在同一时间内能够锁住semaphore之线程的最多个数。

lpName                          Semaphore的名称(一个字符串)。任何线程(或进程)都可以根据这一名称引用到这个semaphore。这个值可以是NULL,意思是产生一个没有名字的semaphore

返回值:

       如果成功就传回一个handle,否则传回NULL。不论哪一种情况,GetLastError( )都回传回一个合理的结果。如果指定的semaphore名称已经存在,则该函数还是成功的,GetLastError( )会传回ERROR_ALREADY_EXISTS

 

ReleaseSemaphore

函数功能:

该函数将指定信号对象的计数增加一个指定的数量。

函数原型:

ReleaseSemaphore(

     HANDLE hSemaphore,

     LONG lReleaseCount,

     LPLONG lpPreviousCount

);

参数:

hSemaphore            Semaphorehandle

lReleaseCount         Semaphore现值的增额。该值不可以是负值或0

lpPreviousCount          藉此传回semaphore原来的现值。

返回值:

       如果成功,则传回TRUE。否则传回FALSE。失败时可调用GetLastError( )获得原因。

备注:

       ReleaseSemaphore( ) 对于semaphore所造成的现值的怎增加,绝对不会超过CreateSemaphore( )时所指定的lMaximumCount

       请记住,lpPreviousCount所传回来的是一个瞬间值。你不可以把lReleaseCount加上 *lpPreviousCount,就当作是semaphore的现值,因为其他线程可能已经改变了semaphore的值。

       mutex不同的是,调用ReleaseSemaphore( )的那个线程,并不一定就得是调用Wait…( )的那个线程。任何线程都可以在任何时间调用ReleaseSemaphore( ),解除被任何线程锁定的semaphore

 

 

 

数据类型

说明

WORD

16位无符号整数

LONG

32位有符号整数

DWORD

32位无符号整数

HANDLE

句柄

UINT

32位无符号整数

BOOL

布尔值

LPISTR

指向字符串的32位指针

LPCTSTR

指向字符串常量的32位指针

 

 

原创粉丝点击