CONTEXT結構在線程調度中起到了重要的作用,在WINDOWS定義的所有結構中,CONTEXT是唯一依賴於CPU的,我們可以通過調用GetThreadContext來獲得當前CPU寄存器的狀態。
BOOL GetThreadContext( HANDLE pThread, PCONTEXT pContext);
這裡有兩個參數pThread是輸入,就是要獲得CPU狀態的線程句柄,第二個參數是CONTEXT結構指針,在分配CONTEXT結構後,需要初始化它的ContextFlag標志,表示要獲取那些狀態寄存器。ContextFlag可以是
CONTEXT_CONTROL 表示控制寄存器
CONTEXT_INTERER 表示整數寄存器
CONTEXT_FLOAT 表示浮點寄存器
CONTEXT_ALL 表示全部寄存器
在調用GetThreadContext之前需要調用SuspendThread掛起線程,注意這個GetThreadContext只能獲得用戶模式上下文,當掛起線程的時候,線程正在內核模式運行,那麼線程將繼續運行知道返回用戶模式時候才掛起,我們不僅可以獲得線程的上下文還能夠設置它
BOOL SetThreadContext() HANDLE hThread, CONST CONTEXT *pContext);
下面來講進程的優先級
就緒的線程在等待CPU的時候會根據優先級的大小來分配CPU,所以優先級和線程的調度有著密切的關系。
Windows的線程優先級從0到31。每個線程都會分配一個優先級。當系統確定給哪個線程分配cpu時,它會首先查看優先級為31的線程,直至所有優先級為31的線程都被調度。然後再查看下一優先級線程。只要存在優先級為31的線程,系統就不會調度0-30級的線程。低優先級線程長時間得不到cpu時間,這被稱為饑餓。這不經常出現,因為大多數線程都是不可調度的。
系統啟動時會創建一個優先級為0的idle線程,整個系統只有它的優先級為0。它在系統中沒有其他線程運行時將系統內存中所有閒置頁面清0。
線程的優先級是有線程所屬的進程的優先級優先級類)和線程的相對優先級相加來確定的,這個值被稱為線程的基本優先級。
WINDOWS支持6個優先級類:
idle,below normal,normal,above normal,high和real-time。當然,normal是最常用的優先級類,為99%的應用程序所使用。
WINDOWS支持7個相對線程優先級
idle,lowest ,below normal,normal,above normal,highest和time-critical。這些優先級是相對於進程優先級的。大多數的線程使用normal優先級。
在創建進程的時候我們可以通過改變fdwCreate參數的值來改變進程的優先級
real-time REALTIME_PRIORITY_CLASS high HIGH_PRIORITY_CLASS above normal ABOVE_NORMAL_PRIORITY_CLASS normal NORMAL_PRIORITY_CLASS below_normal BELOW_NORMAL_PRIORITY_CLASS idle IDLE_PRIORITY_CLASS
在進程運行後,可以通過SetPrioritClass來設置進程的優先級類。
BOOL SetPriorityClass( HANDLE hProcess, DWORD fdwPriority);
可以調用DWORD GetPriorityClass(HANDLE hProcess);來獲得進程的優先級類
上面是指定的進程優先級類,調用CreateThread創建線程時,它的線程優先級總是被設置為normal。可以調用以下函數來改變線程優先級:
BOOL SetThreadPriority( HANDLE hThread, int nPriority);
nPriority可以是以下標識符:
time-critical THREAD_PRIORITY_TIME_CRITICAL
highest THREAD_PRIORITY_HIGHEST
above-normal THREAD_PRIORITY_ABOVE_NORMAL
normal THREAD_PRIORITY_NORMAL
below-normal THREAD_PRIORITY_BELOW_NORMAL
lowest THREAD_PRIORITY_LOWEST
idle THREAD_PRIORITY_IDLE
相應的可以調用int GetThreadPriority(HANDLE hThread);返回線程相對優先級。
Windows並沒有返回線程優先級的函數,而是分別提供返回進程優先級類和相對線程優先級。
有些時候,系統也會提升一個線程的優先級。比如某個線程正在等待用戶按鍵消息。當用戶敲了一個鍵,系統會在線程的消息隊列中放入一個WM_KEYDOWN消息。此時線程就變成可調度的了。鍵盤設備驅動程序將使系統臨時提升線程的優先級。在該時間片結束後,系統會將線程的優先級值減一,第三個時間片執行時再減去一。直至保持基本優先級運行。
注意:線程的當前優先級不會低於進程的基本優先級。而且設備驅動程序可以決定動態提升的幅度。系統只提升優先級值在1~15的線程。這個范圍被稱為動態優先級范圍。可以通過調用以下函數來禁止系統對線程優先級進行動態 提升:
BOOL SetProcessPriorityBoost( HANDLE hProcess, BOOL bDisablePriorityBoost);
此函數禁止動態提升此進程內的所有線程的優先級。
BOOL SetThreadPriorityBoost( HANDLE hThread, BOOL bDisablePriorityBoost);
此函數禁止動態提升某個線程的優先級。
還有一種動態提升優先級的情況:檢測到有饑餓情況出現時,也就是某個線程由於優先級低,而長時間無法得到調度時。系統就會動態提升此線程的優先級。系統允許它運行兩個時間片。兩個時間片結束之後立即恢復到基本優先級。
用戶正在使用的窗口被稱為前台窗口。這個進程就被稱為前台進程。為了改進前台進程的響應性,windows會為前台進程中的線程微調調度算法。是前台進程的線程分配比一般情況下更多的時間片。
關聯性
默認情況下,windows在分配cpu時采用軟關聯的方式。也就是說在其他因素相同的情況下,系統使線程在上一次運行的處理器上運行。這有助於重用仍在處理器高速緩存中的數據。
系統在啟動時確定cpu數量。應用程序可以通過調用GetSysInfo來查詢cpu的數量。如果需要限制一個進程的所有線程在某些cpu上運行,可以調用:
BOOL SetProcessAffinityMask( HANDLE hProcess, DWORD_PTR dwProcessAffinityMask);
第一個參數代表要設置的進程句柄。
第二參數是一個位掩碼。代表線程可以在哪些cpu上運行。
注意子進程將繼承父進程的關聯性。
GetProcessAffinityMask返回進程的關聯掩碼。
相應的還可以設置某個線程只在一組cpu上運行:
SetThreadAffinityMask。
有時候強制一個線程只在某個特定的cpu上運行並不是什麼好主意。Windows允許一個線程運行在一個cpu上,但如果需要,它將被移動到一個空閒的cpu上。
要給線程設置一個理想的cpu,可以調用:
DWORD SetThreadIdealProcessro( HANDLE hThread DWORD dwIdealProcessor);
dwIdealProcessor是一個0到31/63之間的整數。表示線程希望設置的cpu。可以傳入MAXIMUM_PROCESSOR值,表示沒有理想的cpu。
本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1301097