进程和线程
写在前,下面是我读Windows SDK的一些笔记,希望能与需要它的人一起分享。其中有些部分还未读完,我会尽快完善。
1创建线程
可用CreateThread创建一个线程,创建线程的时候必须指明新线程的执行地址,通常它的执行地址就是在程序代码内定义的函数的名称,这个函数只有一个参数,返回的是一个DWORD类型的值。一个进程可以有多个线程同时在执行相同的函数。
如果主建线程在新线程(子线程)前退出程序,那么传地址的方式传递局部变量给新线程就会存在风险,因为指针会变成无效的,所以必须等新线程退出后才能退出子线程。也可以用全局变量来传参数给新线程,但是这就要注意多线程的同步访问。但有的时候,在创建多线程时使用全局变量将不太方便。
对于CreateThread函数的参数,主建线程可以使用的参数有如下几个:
第一个:新线程的安全属性(security
attributes)。该属性表明一个子进程是否能够继承该新线程。安全属性也被系统用来在允许访问之前检查所有对这个线程的并发访问。
第二个:新线程的初始栈空间(initial
stack size)大小。线程的栈被自动分配在进程的内存空间内,系统在线程被创建时分配栈并在线程结束时释放栈。
第三个:创建标识(creation
flag)使你在挂起状态下创建这个线程。挂起后,直到ResumeThread函数被调用后线程才会被调用。
你也可以用CreateRemoteThread函数来创建一个线程。不过这个函数多用于调试进程在被调试的进程的地址空间内创建一个运行在该空间内的线程。
(2005-4-12)
2挂起线程的执行
通过使用SuspendThread和ResumeThread函数可以将一个线程挂起和激活执行。当一个线程被挂起后,处理器将不为它分配预定的时间。SuspendThread函数不适合用于线程的同步,因为它无法控制代码内,线程的执行在哪一点被挂起。
3多个线程的同步执行
为了避免竞争和死锁,多线程对共享资源的同步访问是有必要的。同步还确保相互以来的代码以合适的顺序执行。
有很多的对象可以用于同步多线程。这些对象包括:
控制输入缓冲区
事件互斥 进程
信号量线程计时器
这些对象中的一些常用于阻塞一个线程直到某个事件发生。例如,
其他的对象对于保护共享资源不被同时访问是非常有用的。例如,
对于一个单进程的多个线程,临界区(critical-section)对象提供的同步方法比互斥对象更有效。临界区可以像互斥对象一样,使得在某一个时间只有一个线程去使用受保护的资源。一个线程可以调用EnterCriticalSection函数来请求某个临界区的所有权。如果它正在被另一个线程使用,那么这个发起请求的线程被阻塞。一个线程也可以调用TryEnterCriticalSection函数来请求某个临界区的所有权,此时即使请求失败也不会被阻塞。在获得临界区所有权后,线程可以自由地使用受保护资源。该进程的其它线程如果不试图进入临界区,它们的执行就不会受到影响。
WaitForInputIdle函数使一个线程等待直到一个指定的进程被初始化并且等待用户输入一个确定的输入。调用WaitForInputIdle函数可以被用于同步的父进程和子进程,因为CreateProcess函数不用等到子进程完成初始化才返回。
4线程的局部存储
5中止一个线程
6线程安全和访问权限
Windows NT安全模式使你可以控制对线程对象的访问。当你调用CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW,
CreateThread, 或者CreateRemoteThread函数时,你可以为一个线程指定一个安全描述符(security
descriptor)。如果你指定为NULL,该线程将得到一个默认的安全描述符。线程中的默认安全描述符的ACL是主要的或者是像创建者的标识(token)一样重要。
(2005-4-13)
GetSecurityInfo函数可用来获得某个线程的安全描述符,SetSecurityInfo函数可用来改变某个线程的安全描述符。
由CreateThread函数返回的句柄拥有THREAD_ALL_ACCESS的权限来访问那个线程对象。当你调用GetCurrentThread函数时,系统返回一个安全描述符允许的具有最小访问权限的伪句柄给调用者。
对线程对象合法的访问权限包括DELETE,READ_CONTROL,SYNCHRONIZE,WRITE_DAC,and WRITE_OWNER这些标准访问权限,此外,下面的是一些线程的特殊访问权限:
值
含义
SYNCHRONIZE
可以在任何的等待函数中使用线程句柄
THREAD_ALL_ACCESS
线程对象的所有可能访问权限
THREAD_DIRECT_IMPERSONATION
一个模仿客户的服务器线程所必须的
THREAD_GET_CONTEXT
使用GetThreadConttext读取某个线程的上下文时所必须的
THREAD_IMPERSONATE
Required to use a thread's security
information directly without calling it by using a communication mechanism
that provides impersonation services.
THREAD_QUERY_INFORMATION
从某个线程读取确定信息(例如退出代码,参看GetExitCodeThread函数)所必须的。
THREAD_SET_CONTEXT
使用SetThreadContext写一个线程的上下文时所必须的
THREAD_SET_INFORMATION
在线程对象中设置确定的信息时所必须的
THREAD_SET_THREAD_TOKEN
Required to set the impersonation token
for a thread using SetTokenInformation.
THREAD_SUSPEND_RESUME
挂起或激活一个线程时所必须的
THREAD_TERMINATE
使用TerminateThread函数中止一个线程时所必须的
如果想读或写一个线程对象的SACL(安全控制列表)时,你可以对该线程使用ACCESS_SYSTEM_SECURITY的访问权限。