程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> WINDOWS核心編程學習心得--線程上下文、優先級和相關性

WINDOWS核心編程學習心得--線程上下文、優先級和相關性

編輯:關於C語言

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved