windows 系统编程 Chap7 线程和调度
7.2 线程基础 P162
进程中的线程共享相同的代码和数据,所以线程必须也具有自身的唯一存储方式。Windows以几种方式满足:
- 每个线程都有自身的堆栈以便在函数调用和其他进程中使用
- 调用函数可以传递参数,通常在创建时每个线程一个指针。参数实际上在线程堆栈中
- 每个线程可以分配自身的线程本地存储(TLS)索引并读取和设置TLS值。
Windows通过允许不同的线程,甚至来自同一进程的线程在不同的处理器上并发运行以使用SMP系统。
7.3 线程管理
线程就像其他Windows对象一样具有句柄,而且有一个系统调用CreateThread可以在调用进程地址空间中创建一个可执行线程
CreateThread独特的要求:
- 指定线程在进程代码中的开始地址
- 指定堆栈大小,堆栈空间是从进程虚拟地址空间中分配的。缺省堆栈大小是父线程的虚拟内存堆栈大小(通常1M)
- 指定线程参数指针。该参数几乎可以是任何值并被线程自身解释。
- CreateThread返回一个线程ID值及其句柄。一个NULL句柄值表示一个失败。
7.3.1 线程标识
GetCurrentThreadId获取线程ID而不是句柄。
GetThreadId可以从句柄获取线程ID,需要Windows2003
OpenThread从线程ID创建线程句柄
7.3.2 其他线程管理函数
7.3.3 挂起和恢复线程
每个线程具有一个挂起计数器,而一个线程只能在该计数器是0时才可以执行。一个线程可以通过使用SuspendThread和ResumeThread来增加或减少另一个线程的挂起数量。
DWORD SuspendThread(HANDLE hThread)
DWORD ResumeThread(HANDLE hThread)
两个函数如果成功就返回前面挂起的数量。0xFFFFFFFF则表示失败。
7.3.4 等待线程终止
用线程句柄代替进程句柄并使用等待函数(WaitForSingleObject或WaitForMultipleObjects)
WaitForMultipleObjects一次只能等待MAXIMUM_WAIT_OBJECTS(64)个句柄,但是如果有大量的线程可以多次执行等待。
7.3.5 远程线程
CreateRemoteThread函数允许在其进程中创建一个线程。
7.4 在线程中使用C库
C库是用来在单线程进行的,所以许多函数使用全局存储来保存中间结果。这样的库不具备线程安全性。
7.9 线程局部存储
线程需要独立并隔离于同一进程中的其他线程进行自身的存储分配和管理。
DWORD TlsAlloc(VOID)
BOOL TlsFree(DWORD dwIndex)
单个线程可以使用TLS索引从其位置处获取和设置其值(空指针)
LPVOID TlsGetValue(DWORD dwTlsIndex)
BOOL TlsSetValue(DWORD dwTlsIndex)
BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
7.10 进程和线程优先级和调度
通过CreateProcess可以初始设置的进程优先级有四类,而每类具有基本优先级
IDLE_PRIORITY_CLASS 基本优先级4
7.11 线程状态
执行程序是如何管理线程的以及可能的线程状态。
7.12 缺陷和常见错误
7.13 计时等待
7.14 纤程
7.15 总结
7.15.2 推荐读物
《Multithreading Applications in Win32》 侯捷译的
还有一本是自己加的《windows internel》 潘爱民译的