Windows操作系統(tǒng)多核CPU內(nèi)核線程管理方法
摘要:Windows 是采用CPU 時間片輪轉(zhuǎn)多任務(wù)分配機制的非實時操作系統(tǒng),無法滿足實時性要求比較高的任務(wù)需要。而隨著CPU技術(shù)的快速發(fā)展,當(dāng)前市場上雙核甚至多核CPU 已成為主流,這使得在Windows 平臺上用多核CPU 的某些核獨立執(zhí)行任務(wù),從而有效地提高軟件的實時性成為可能。本文介紹一種在Windows 內(nèi)核模式下編寫Windows 驅(qū)動程序,有效分配多核CPU 資源從而提高軟件實時性的方法。
1 引言
本文分析了Windows 系統(tǒng)的進(jìn)程調(diào)度機制,并設(shè)計了一種基于Windows 操作系統(tǒng)內(nèi)核驅(qū)動的多核CPU 線程管理方法,實現(xiàn)了一個基于Windows 內(nèi)核驅(qū)動的線程管理服務(wù)系統(tǒng),它能讓用戶根據(jù)每一個任務(wù)線程對CPU 資源的需要程度和對實時性的要求,在多核CPU上合理為線程分配CPU 核。
Windows 內(nèi)核調(diào)度結(jié)構(gòu)體關(guān)系圖
圖1 Windows 內(nèi)核調(diào)度結(jié)構(gòu)體關(guān)系圖
2 Windows 系統(tǒng)的進(jìn)程調(diào)度方法分析
Windows NT 中的每一個進(jìn)程都是EPROCESS 結(jié)構(gòu)體。此結(jié)構(gòu)體中除了進(jìn)程的屬性之外還引用了其它一些與實現(xiàn)進(jìn)程緊密相關(guān)的結(jié)構(gòu)體。例如,每個進(jìn)程都有一個或幾個線程,線程在系統(tǒng)中就是ETHREAD 結(jié)構(gòu)體。簡要描述一下存在于這個結(jié)構(gòu)體中的主要的信息,這些信息都是由對內(nèi)核函數(shù)的研究而得知的。首先,結(jié)構(gòu)體中有KPROCESS 結(jié)構(gòu)體,這個結(jié)構(gòu)體中又有指向這些進(jìn)程的內(nèi)核線程(KTHREAD)鏈表的指針(分配地址空間),基優(yōu)先級,在內(nèi)核模式或是用戶模式執(zhí)行進(jìn)程的線程的時間,處理器affini ty(掩碼,定義了哪個處理器能執(zhí)行進(jìn)程的線程),時間片值。在ETHREAD 結(jié)構(gòu)體中還存在著這樣的信息:進(jìn)程ID、父進(jìn)程ID、進(jìn)程映象名。
在E P R O C E S S 結(jié)構(gòu)體中還有指向P E B 的指針。
ETHREAD 結(jié)構(gòu)體還包含有創(chuàng)建時間和退出時間、進(jìn)程ID 和指向EPROCESS 的指針,啟動地址,I/O 請求鏈表和KTHREAD 結(jié)構(gòu)體。在KTHREAD 中包含有以下信息:內(nèi)核模式和用戶模式線程的創(chuàng)建時間,指向內(nèi)核堆棧基址和頂點的指針、指向服務(wù)表的指針、基優(yōu)先級與當(dāng)前優(yōu)先級、指向APC 的指針和指向T E B 的指針。
KTHREAD 中包含有許多其它的數(shù)據(jù),通過觀察這些數(shù)據(jù)可以分析出KTHREAD 的結(jié)構(gòu)。圖1 描述了這些結(jié)構(gòu)體之間的關(guān)系。
通過遍歷KPROCESS 結(jié)構(gòu)體中的ETHREAD,找到系統(tǒng)中當(dāng)前所有的KTHREAD 結(jié)構(gòu),這個結(jié)構(gòu)中的偏移量為0x124 處的Affinity 域(Windows XP sp3)即為設(shè)置CPU 親緣性掩碼的內(nèi)存地址。在此重點解釋CPU 親緣性的概念,CPU 親緣性就是指在系統(tǒng)中能夠?qū)⒁粋€或多個進(jìn)程或線程綁定到一個或多個處理器上運行,這是期待已久的特性。也就是說:“ 在1號處理器上一直運行該程序”或者是“在所有的處理器上運行這些程序,而不是在0 號處理器上運行”。然后, 調(diào)度器將遵循該規(guī)則,程序僅僅運行在允許的處理器上。在Windows 操作系統(tǒng)上,給程序員設(shè)定CPU 親緣性的接口是用一個32 位的雙字型數(shù)表示的, 它被稱為親緣性掩碼(Affinity bitMask)。親緣性掩碼是一系列的二進(jìn)制位,每一位代表一個CPU 單元是否可執(zhí)行當(dāng)前任務(wù)。例如一個在具有四個CPU 的PC 機上( 或四核CPU) ,親緣性掩碼的形式的二進(jìn)制數(shù)如下式所示:
0000000000000000000000000000XXXXB
其中自右向左,每一位代表0 到31 號CPU是否可用,由于本機只有四個CPU, 所以只有前四個位可用,X 為1則代表當(dāng)前任務(wù)可執(zhí)行在此位代表的CPU 上,X 為0 則代表當(dāng)前任務(wù)不可執(zhí)行在此位代表的CPU 上, 例如:
00000000000000000000000000000010B
代表當(dāng)前任務(wù)只能執(zhí)行在1 號 CPU 上(CPU 下標(biāo)記數(shù)從0 開始),又如0x00000004 代表當(dāng)前任務(wù)只能執(zhí)行在2 號CPU 上,0x00000003 代表當(dāng)前任務(wù)可以運行在0號和1 號CPU 上。
Windows 的進(jìn)程調(diào)度代碼是在它的SySTem 進(jìn)程下的,所以它不屬于任何用戶進(jìn)程上下文。調(diào)度代碼在適當(dāng)?shù)臅r機會切換進(jìn)程上下文,這里的切換進(jìn)程上下文是指進(jìn)程環(huán)境的切換, 包括內(nèi)存中的可執(zhí)行程序, 提供程序運行的各種資源.進(jìn)程擁有虛擬的地址空間,可執(zhí)行代碼, 數(shù)據(jù), 對象句柄集, 環(huán)境變量, 基礎(chǔ)優(yōu)先級, 以及最大最小工作集等的切換。而Windows 最小的調(diào)度單位是線程, 只有線程才是真正的執(zhí)行體,進(jìn)程只是線程的容器。Windows 的調(diào)度程序在時間片到期,或有切換線程指令執(zhí)行(如Sleep,KeWaitForSingleObject 等函數(shù))時, 將會從進(jìn)程線程隊列中找到下一個要調(diào)度的線程執(zhí)行體,并裝入到KPCR(Kernel ' s Processor CONtr ol Re g i o n , 內(nèi)核進(jìn)程控制區(qū)域) 結(jié)構(gòu)中,CPU 根據(jù)KPCR 結(jié)構(gòu)中的KPRCB 結(jié)構(gòu)執(zhí)行線程執(zhí)行體代碼。而在多核CPU 下,當(dāng)Windows 調(diào)度代碼執(zhí)行時,從當(dāng)前要調(diào)度執(zhí)行的KTHREAD 結(jié)構(gòu)中取出Affinity,并與當(dāng)前PC 機上的硬件配置數(shù)據(jù)中的CPU 掩碼作與操作,結(jié)果寫入到指定的CPU,例如雙核CPU 的設(shè)備掩碼為0x03,如果當(dāng)前KTHREAD 里的Affinity 為0x01,那么0x010x03=0x01,這樣執(zhí)行體線程會被裝入CPU1的KPRCB 結(jié)構(gòu)中得以執(zhí)行,調(diào)度程序不會把這個線程交給CPU2 去執(zhí)行。此過程如圖2 所示。這就是為線程選擇指定CPU 核的原理。
評論