2.备用APC队列
如果想讓線程做什么事情,就給它的APC隊(duì)列里面掛一個(gè)APC。
kd> dt _kthread nt!_KTHREAD ... +0x034 ApcState : _KAPC_STATE//APC ... +0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE//APC指針 ... +0x14c SavedApcState : _KAPC_STATE//備用APC ... +0x165 ApcStateIndex : UChar//線程狀態(tài) +0x166 ApcQueueable : UChar//當(dāng)前成員是否允許插入APC ...SavedApcState的意義
線程APC隊(duì)列中的APC函數(shù)都是與進(jìn)程相關(guān)聯(lián)的,具體點(diǎn)說(shuō): A進(jìn)程的, T線程中的所有APC函數(shù),要訪問(wèn)的內(nèi)存地址都是A進(jìn)程的。
但線程是可以掛靠到其他的進(jìn)程:比如A進(jìn)程的線程T,通過(guò)修改 Cr3(改為B進(jìn)程的頁(yè)目錄基址),就可以訪問(wèn)B進(jìn)程地址空間,即所謂"進(jìn)程掛靠".
當(dāng)T線程掛靠B進(jìn)程后, APC隊(duì)列中存儲(chǔ)的卻仍然是原來(lái)的APC!具體,點(diǎn)說(shuō),比如某個(gè)APC函數(shù)要讀取一個(gè)地址為0x12345678的數(shù)據(jù),如果此時(shí)進(jìn)行 讀取,讀到的將是B進(jìn)程的地址空間,這樣邏輯就錯(cuò)誤了!
為了避免混亂,在T線程掛靠B進(jìn)程時(shí),會(huì)將ApcState中的值暫時(shí)存儲(chǔ)到SavedApcState中,等回到原進(jìn)程A時(shí),再將APC隊(duì)列恢復(fù)
SavedApcState又稱為備用APC隊(duì)列。
掛靠環(huán)境下ApcState的意義
在掛靠的環(huán)境下,也是可以先線程APC隊(duì)列插入APC的,那這種情況下, 使用的是哪個(gè)APC隊(duì)列呢?
A進(jìn)程的T線程掛靠B進(jìn)程 A是T的所屬進(jìn)程 B是T的掛靠進(jìn)程
ApcState: B進(jìn)程相關(guān)的APC函數(shù)
SavedApcState: A進(jìn)程相關(guān)的APC函數(shù)
在正常情況下,當(dāng)前進(jìn)程就是所屬進(jìn)程A,如果是掛靠情況下,當(dāng)前進(jìn)程就是掛靠進(jìn)程B.
+0x138 ApcStatePointer
為了操作方便, KTHREAD結(jié)構(gòu)體中定義了一個(gè)指針數(shù)組ApcStatePointer ,長(zhǎng)度為2.
正常情況下:
ApcStatePointer[0] 指向 ApcState
ApcStatePointer(1] 指向 SavedApcState
掛靠情況下:
ApcStatePointer(0] 指向 SavedApcState
ApcStatePointer(1] 指向 ApcState
+0x165 ApcStatelndex
ApcStatelndex用來(lái)標(biāo)識(shí)當(dāng)前線程處于什么狀態(tài):
0正常狀態(tài)
1掛靠狀態(tài)
ApcStatePointer與ApcStatelndex組合尋址
正常情況下,向ApcState隊(duì)列中插入APC時(shí):
- ApcStatePointer[0] 指向 ApcState 此時(shí) ApcStatelndex的值為0
- ApcStatePointer[ApcStatelndex] 指向ApcState
掛靠情況下,向ApcState隊(duì)列中插入APC時(shí):
- ApcStatePointer[1]指向ApcState此時(shí)ApcStatelndex的值為1
- ApcStatePointer[ApcStateIndex] 指向 ApcState
無(wú)論什么環(huán)境下, ApcState Pointer[ApcStateIndex]指向的都是ApcState ApcState則總是表示線程當(dāng)前使用的apc狀
+0x166 ApcQueueable
ApcQueueable用于表示是否可以向線程的APC隊(duì)列中插入APC。
當(dāng)線程正在執(zhí)行退出的代碼時(shí),會(huì)將這個(gè)值設(shè)置為0,如果此時(shí)執(zhí)行.插入APC的代碼(KelnsertQueueApc后面會(huì)講),在插入函數(shù)中會(huì)判斷這個(gè)值的狀態(tài),如果為0,則插入失敗。
總結(jié)
- 上一篇: 1.APC机制
- 下一篇: 3.APC的挂入过程