線程的創建過程與終止過程

以下文字片段摘自書籍<<Windows 併發編程指南>>,所有權歸原著者,這裏僅做交流分享.

線程創建的具體流程

當Windows 創建一個新的線程時,無論是通過Win32的API還是.NET框架的API,都會執行以下的步驟(大致是這個順序)

  1. 分配一些重要的線程數據結構,例如 KTHREAD,ETHREAD 以及TEB. 我們在上面已經介紹了這些結構。此外,還將分配和初始化一些結構用於異步過程調用(Asynchronous Procedure Call, APC)、本地過程調用(Local Procedure Call, LPC)、內存管理,I/O, 互斥體所有權,以及線程創建信息等。然後將生成一個唯一的線程ID。
  2. 分配線程的上下文,其中包好了特定於CPU的寄存器信息。這將生成一個CONTEXT 結構,它將在隨後上下文切換期間被用於捕獲和恢復處理器的狀態。我們可以通過GetUserContext來訪問這個數據結構。
  3. 創建進程地址空間中的用戶態棧。我們可以在創建線程或者配置線程信息時通過參數來控制線程棧的保留大小和提交大小,這在前面已經介紹過了。隨後,將創建和初始化內核態棧。
  4. Windows 子系統進程CRSS.exe 將收到新線程創建的通知,此時它可以記錄一些在初始化線程狀態和執行線程時需要的信息。
  5. 進程的第一個線程再執行線程起始執行函數之前必須完成進程的初始化工作,包括加載所需的DLL,通過附加到進程的調試器打開調試端口,初始化系統服務,初始化TLS以及相關的數據結構,並且將DLL_PROCESS_ATTACH通知發送給進程中所有已加載的DLL的DllMain函數。
  6. 將DLL_THREAD_ATTACH 通知發送給進程中的所有DLL。
  7. 如果在創建線程時沒有設置CREATE_SUSPENDED標誌,那麼線程將立即開始運行。Windows線程調度器將把它分配到某個處理器上執行。在這些操作完成之後,線程將從線程起始執行函數開始執行。
  8. 線程創建函數返回。在Win32 的CreateThread情況中,返回值是新線程的句柄,而出口參數線程ID將被設置爲分配給這個線程的唯一標識。

線程終止的具體流程

我們已經看到了,根據線程是順利地退出還是通過TerminateThread被強制結束,線程的終止過程將略有不同。正如在線程創建過程中有一些共同的步驟,在線程終止過程中通常也有一些共同的步驟。在前面已經介紹了在線程終止過程中需要注意的各種異常。

  1. 將DLL_THREAD_DETACH通知發送到進程中每個已加載的DLL。TerminateThread將跳過這個步驟。
  2. 線程內核對象被設置爲已觸發狀態。觸發線程對象意味着,你可以像其他Win32同步事件或者原語那樣來使用線程的句柄。
  3. 釋放用戶態的棧。與DLL通知的情況一樣,TerminateThread將不會執行這個步驟。相反,被強行結束的線程中的用戶態棧將在進程退出時被釋放。
  4. 所有的內核態棧數據結構,包括棧、上下文、TEB、TLS內存以及在前面提到的在創建過程中分配的其他與線程相關的數據結構都將被釋放。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章