进程线程006 Windows线程切换-线程优先级
文章目錄
- 內(nèi)容回顧
- 調(diào)度鏈表
- 如何高效查找
- 如果沒(méi)有就緒線程怎么辦
內(nèi)容回顧
之前我們已經(jīng)了解過(guò),有三種情況會(huì)導(dǎo)致線程切換:
KiSwapContext和KiQuantumEnd函數(shù)中都是通過(guò)KiFindReadyThread來(lái)找下一個(gè)要切換的線程,這次要解決的問(wèn)題是KiFindReadyThread是根據(jù)什么條件來(lái)選擇下一個(gè)要執(zhí)行的線程。
調(diào)度鏈表
kd> dd KiDispatcherReadyListHead 8055bc20 8055bc20 8055bc20 8055bc28 8055bc28 8055bc30 8055bc30 8055bc30 8055bc38 8055bc38 8055bc40 8055bc40 8055bc40 8055bc48 8055bc48 8055bc50 8055bc50 8055bc50 8055bc58 8055bc58 8055bc60 8055bc60 8055bc60 8055bc68 8055bc68 8055bc70 8055bc70 8055bc70 8055bc78 8055bc78 8055bc80 8055bc80 8055bc80 8055bc88 8055bc88 8055bc90 8055bc90 8055bc90 8055bc98 8055bc98線程的調(diào)度鏈表一共有32個(gè),這32個(gè)是按照不同的級(jí)別存放在一起的。例如線程級(jí)別為0的掛到0號(hào)鏈表里,線程級(jí)別為1的掛到1號(hào)鏈表里。
KiFindReadyThread查找線程的方式—>按照優(yōu)先級(jí)進(jìn)行查找:31…30…29…28。也就是說(shuō),在本次查找中,如果級(jí)別31的鏈表里面有線程,那么就不會(huì)查找級(jí)別為30的鏈表
這并不意味著線程級(jí)別高的線程執(zhí)行完了才能執(zhí)行線程級(jí)別低的線程,在查找的時(shí)候,每次只會(huì)查找線程級(jí)別最高的那個(gè)線程,但是高級(jí)別的線程在執(zhí)行的時(shí)候,如果調(diào)用了API或者CPU時(shí)間片到期,低級(jí)別的線程仍然是有機(jī)會(huì)執(zhí)行的。
如何高效查找
調(diào)度鏈表有32個(gè),每次從頭查找效率太低,所以Windows在這方面做了一個(gè)優(yōu)化。
Windows定義了一個(gè)DWORD類型的變量來(lái)記錄:
DWORD類型的變量有32位,里面的每一位分別對(duì)應(yīng)當(dāng)前某一個(gè)鏈表里面是否有正在等待調(diào)度的線程。
當(dāng)向調(diào)度鏈表中掛入或者刪除某個(gè)線程的時(shí)候,會(huì)判斷當(dāng)前級(jí)別的鏈表是否為空,為空則將DWORD變量對(duì)應(yīng)位置置0,否則置1
當(dāng)某一個(gè)時(shí)刻,這個(gè)DWORD類型的變量轉(zhuǎn)換為二進(jìn)制的值如上圖的時(shí)候,意味著在32個(gè)鏈表里,線程級(jí)別為30的鏈表里有等待調(diào)度的線程,線程級(jí)別為29的鏈表里也是有等待調(diào)度的線程。其他的鏈表則沒(méi)有等待調(diào)度的線程。
這個(gè)變量:_kiReadySummary
如果沒(méi)有就緒線程怎么辦
在KPCR里面有一個(gè)子結(jié)構(gòu)體PrcbData,這個(gè)子結(jié)構(gòu)體有三個(gè)重要的成員,如下
PrcbData: +0x004 CurrentThread : Ptr32 _KTHREAD +0x008 NextThread : Ptr32 _KTHREAD +0x00c IdleThread : Ptr32 _KTHREAD- CurrentThread:當(dāng)前正在運(yùn)行的線程
- NextThread:下一次準(zhǔn)備運(yùn)行的線程,也就是備用線程
- IdleThread:空閑線程,當(dāng)前的CPU查找調(diào)度鏈表發(fā)現(xiàn)里面已經(jīng)沒(méi)有需要調(diào)度的線程的時(shí)候,就會(huì)運(yùn)行這個(gè)線程
下面通過(guò)代碼論證,首先找到KiFindReadyThread
交叉引用找到上一層調(diào)用它的函數(shù),以KiSwapThread為例
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-wl5LlG80-1581510940435)(assets/1581478367459.png)]
這里調(diào)用了KiFindReadyThread查找一個(gè)就緒線程,然后判斷是否為空,如果為空則繼續(xù)往下執(zhí)行
.text:00429162 mov eax, [esi+0Ch]這里的esi就是PrcbData結(jié)構(gòu)體,+0xC的位置就是IdleThread,這里取出IdleThread放到eax里
.text:0042916C or _KiIdleSummary, edx接著修改這個(gè)全局變量
然后繼續(xù)調(diào)用KiSwapContext進(jìn)行線程切換,這個(gè)時(shí)候切換的目標(biāo)線程就是IdleThread
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的进程线程006 Windows线程切换-线程优先级的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 进程线程005 SwapContext函
- 下一篇: Windows保护模式学习笔记(一)——