线程的数据结构
除非顯式地聲明,否則,你可以假設(shè)以下討論的內(nèi)容既適合用戶模式的線程,也適用于內(nèi)核模式的線程。
在系統(tǒng)級別上,Windows線程是由一個(gè)線程塊執(zhí)行體(ETHREAD)來表示的,如圖6.7所示。ETHREAD塊和它所指向的結(jié)構(gòu)都位于系統(tǒng)地址空間中,唯一的例外是線程環(huán)境快(TEB),它位于進(jìn)程地址空間中。而且,Windows子系統(tǒng)進(jìn)程(Csrss)為Windows進(jìn)程中創(chuàng)建的每個(gè)線程維護(hù)了一個(gè)平行結(jié)構(gòu)。另外,對于那些調(diào)用了任何一個(gè)Windows子系統(tǒng)USER或GDI函數(shù)的線程,Windows子系統(tǒng)內(nèi)核模式部分(Win32k.sys)為它維護(hù)了一個(gè)稱為W32THREAD的數(shù)據(jù)結(jié)構(gòu),線程的ETHREAD塊指向此結(jié)構(gòu)。
圖6.7中的大多數(shù)字段的意義已經(jīng)很明了,不用多說了。第一個(gè)字段是內(nèi)核線程塊(KTHREAD)。緊隨其后的是線程標(biāo)識信息、進(jìn)程標(biāo)識信息(包括一個(gè)指向所有進(jìn)程的指針,因而可以訪問它的環(huán)境信息)、安全信息(包括一個(gè)指向訪問令牌的指針以及身份模擬信息),最后是與LPC消息和待處理I/O請求有關(guān)的字段。關(guān)于ETHREAD塊的信息,你可以使用內(nèi)核調(diào)試器的lkd> dt nt!_ethread(對應(yīng)進(jìn)程的是_eprocess)命令來顯示其數(shù)據(jù)結(jié)構(gòu)。
現(xiàn)在讓我們來看一看兩個(gè)關(guān)鍵的線程數(shù)據(jù)結(jié)構(gòu):KTHREAD和TEB。KTHREAD塊包含了Windows內(nèi)核為這些正在運(yùn)行的線程執(zhí)行線程調(diào)度和同步而需要訪問的信息。它的布局結(jié)構(gòu)如圖6.8所示。
關(guān)于KTHREAD塊的信息,你可以使用內(nèi)核調(diào)試器的lkd> dt nt!_kthread(對應(yīng)進(jìn)程的是_kprocess)命令來顯示其數(shù)據(jù)結(jié)構(gòu)。
圖6.9所示的TEB是本節(jié)中介紹的唯一位于進(jìn)程地址空間中的數(shù)據(jù)結(jié)構(gòu)。
TEB存儲(chǔ)了有關(guān)映像加載器和各種Windows DLL的環(huán)境信息。因?yàn)檫@些組件運(yùn)行在用戶模式下,所以它們需要一個(gè)在用戶模式下可寫的數(shù)據(jù)結(jié)構(gòu)。為什么該結(jié)構(gòu)位于進(jìn)程地址空間中而不是位于系統(tǒng)地址空間中呢?因?yàn)橄到y(tǒng)空間只能在內(nèi)核模式下才可寫。通過內(nèi)核調(diào)試器的lkd> dt nt!thread命令你可以看到TEB的地址,同樣,你也可以用lkd> dt nt!_teb(對應(yīng)進(jìn)程的是_peb)命令來查看TEB的數(shù)據(jù)結(jié)構(gòu)。
線程的上下文
線程的上下文本質(zhì)上是一組處理器的寄存器,有正在執(zhí)行程序中的指針及堆棧指針。上下文及其轉(zhuǎn)換的過程根據(jù)處理器的結(jié)構(gòu)不同會(huì)有所不同。我們可以調(diào)用內(nèi)核調(diào)試器的lkd> dt nt!_context命令來觀察上下文的數(shù)據(jù)結(jié)構(gòu)。
一個(gè)典型的上下文轉(zhuǎn)換需要保存和重載以下的數(shù)據(jù):
- 程序計(jì)數(shù)器;
- 處理器狀態(tài)寄存器;
- 其他寄存器的內(nèi)容;
- 用戶模式和內(nèi)核模式的棧指針;
- 指向運(yùn)行的線程的地址空間的指針,也就是進(jìn)程的頁表項(xiàng)。
內(nèi)核將舊線程的這些信息保存到當(dāng)前內(nèi)核模式的屬于舊線程的棧中,然后更新棧指針,再將
棧指針保存到舊線程的KTHREAD模塊中。接著,內(nèi)核棧指針就會(huì)指向新線程的內(nèi)核棧,新線程的上下文將被裝載。如果新的線程是屬于不同的進(jìn)程,系統(tǒng)將裝載它的頁表目錄項(xiàng)到一個(gè)特殊的處理器寄存器中,讓它的地址空間有效。如果有需要發(fā)送的內(nèi)核APC被掛起,中斷級別是1的中斷產(chǎn)生。否則,控制權(quán)將交給新線程保存的程序計(jì)數(shù)器,線程重新執(zhí)行。
?
說明:
本文摘自《Windows Internals》第6章《進(jìn)程、線程和作業(yè)》6.1《線程的內(nèi)部機(jī)理》
總結(jié)
- 上一篇: WinSock编程基础
- 下一篇: 线程的调度