線程二

一、線程的調度     

   window是搶佔式多線程操作系統,也就是說一個線程可以隨時停止運行,即不管這個線程是否已經消耗完自己的時間片,隨後另一個線程可進行調度。線程的內核對象中使用線程上下文結構(CONTEXT結構)來保存自己線程運行時的CPU寄存器狀態,當線程切換時,都會進行線程上下文切換。

       在線程的內核對象中設定了一個暫停計數。當調用CreateProcess或CreateThread函數時,會創建一個線程內核對象,並且將暫停計數設爲1,這樣就可以阻止線程被調用到CPU,這樣就可以有時間初始化線程。當線程初始化完成後,CreateProcess或CreateThread函數會查看是否傳遞了CREATE_SUSPENDED標誌。如果傳遞了,那麼函數就會返回,線程保持暫停狀態;如果沒有傳遞該標誌,那麼暫停計數就會變爲0,線程就會處於可調度狀態(除非線程正在等待其他事情)。

        當線程處於暫停狀態時,如果我們需要將線程設爲可調度狀態,那麼可以用函數ResumeThread函數來實現。這個函數沒執行一次,暫停計數會減1次,只有暫停計數爲0,線程就可以處於可調度裝填。該函數成功執行成功,會返回前一個暫停計數,否則,返回0XFFFFFFF。該函數如下:

     DWORD ResumeThread(HANDLE hThread);

        除了使用CREATE_SUSPENDED標誌外,還可以使用函數SuspendThread來暫停線程。每次調用該函數,暫停計數都會加1。任何線程夠可以使用該函數來暫停另一個線程,每個線程最多可以暫停次數爲MAXIMUM_SUSPEND_COUNT(在WinNT.h中定義爲127)。
        可以調用Sleep函數讓線程在某個時間段內不被調用,其形式如下:

     VOID Sleep(DWORD dwMilliseocnds);

       關於Sleep函數,有下面幾個問題值得注意:

  • 調用Sleep函數,會自願放棄它剩餘的時間片。
  • 系統將在大約的指定毫秒數內使線程不可調用。
  • dwMilliseocnds如果設爲INFINITE時,表示該線程永遠不會被調用。
  • dwMilliseocnds如果設爲0,表示線程會放棄剩餘的時間片,當會處於可調度狀態。

        可以調用SwitchToThread函數判斷是否有一個急需CPU的線程,如果有,就會對該線程調用,如果沒有,就會繼續系統調用。其形式如下:

     BOOL SwitchToThread();

        可以使用函數GetThreadTimes和GetProcessTimes來獲取線程和進程的運行時間:

    BOOL GetThreadTimes( HANDLE hThread, PFILETIME pftCreationTime, PFILETIME pftExitTime, PFILETIME pftKernelTime, PFILETIME pftUserTime);
     BOOL GetProcessTimes( HANDLE hProcess, PFILETIME pftCreationTime, PFILETIME pftExitTime, PFILETIME pftKernelTime, PFILETIME pftUserTime);

           windows還提供了用於高分辨率性能的函數:

       BOOL QueryPerformanceFrequency(LAGE_INTEGER *pliFequency);
       BOOL QueryPerformanceFCounter(LAGE_INTEGER *pliCount);

           CONTEXT結構對於不同的CPU成員有不同,我們可以通過GetThreadContext函數來獲取線程內核對象CONTEXT結構,可以通過SetThreadContext函數對CONTEXT結構進行設置:

       BOOL GetThreadContext(HANDLE hThread,PCONTEXT pContext);       
      BOOL SetThreadContext(HANDLE hThread,const PCONTEXT pContext);

二、線程的優先級

       在windows中每個線程都被賦予一個0到31的優先級。高優先級的可調度的線程優先被調用。高優先級的線程搶在低優先級的線程前運行,不管這個低優先級的線程的時間片是否用完。在windows中只有一個唯一的0優先級線程,稱爲0頁線程。該線程在系統沒有線程運行時,該線程將系統中的所有空閒RAM頁面置爲0。

       windows的調用算法是變化的,因此在編寫程序時要注意。

       windows的線程優先級由進程的優先級類和相對的線程優先級來決定的。進程的優先級類有6個:空閒、低於正常、正常、高於正常、高和實時。windows支持7個相對的線程優先級:空閒、最低、低於正常、正常、高於正常、最高和關鍵時間優先級。

        windows負責將進程的優先級類和相對的線程優先級映射到具體的一個優先級上(0~31)。不同版本的映射方式可能是變化的,不是一成不變的。

       程序中可以使用SetPriorityClass和GetPriorityClass函數來設置和獲取進程的優先級類,windows運用下面的標識符來代表各種優先級類:

    

sd

         BOOL SetPriorityClass(HANDLE hProcess,DWORD fdwPriority);
         DWORD GetPriorityClass(HANDLE hProcess);

        當一個進程創建時,它的線程的相對線程優先級總是設置爲正常,我們可以通過函數SetThreadPriority和GetThreadPriority來設置和獲取相對的線程優先級。    

         BOOL SetThreadPriority(HANDLE hThread,int nPriority);
         int GetThreadPriority(HANDLE hThread);

sd

        通過將線程的相對優先級和進程的優先級類綜合考慮,我們就能夠確定線程的優先級了。但,有時候線程會動態提高我們線程的優先級,以便我們隊窗口消息或讀取磁盤等I/O事件作出響應;另一個就是一個線程在長時間無法運行時,也會提高線程的優先級。    

        我們可以通過函數來對提高優先級的開關就行管理。SetProcessPriorityBoost函數可以激活或停用進程中所有線程的優先級提高功能;SetThreadPriorityBoost  函數可以激活或停用一個線程的優先級提高功能:

         BOOL SetProcessPriorityBoost(HANDLE hProcess,BOOL DisablePriorityBoost);
        BOOL SetThreadPriorityBoost(HANDLE hThread,BOOL DisablePriorityBoost);

        也可以通過函數來獲取是否設置了優先級提高功能:

         BOOL GetProcessPriorityBoost(HANDLE hProcess,BOOL DisablePriorityBoost);
        BOOL GetThreadPriorityBoost(HANDLE hThread,BOOL DisablePriorityBoost);

三、線程的親緣性
       在windows2000中,系統將線程分配處理器時,使用軟親緣性:在其他因素相同的情況下,會設法將線程分配給上次運行的處理器,這樣就能夠使用上次使用的高速緩存。

    我們可以通過硬親緣性來控制哪個CPU能夠運行某個線程。

    可以通過函數SetProcessAffinityMask來控制進程中的所有線程的運行CPU,通過函數GetProcessAffinityMask來獲取進程中線程可以運行的CPU:

       BOOL SetProcessAffinityMask(HANDLE hProcess,DWORD_PTR pdwProcessAffinityMask);
       BOOL GetProcessAffinityMask(HANDLE hProcess,PDWORD_PTR dwProcessAffinityMask,PDWORD_PTR pdwSystemAffinityMask); 

         可以通過函數SetThreadAffinityMask函數來設置線程的親緣性:       

        DWORD_PRT SetThreadAffinityMask(HANDLE hThread,DWORD_PTR dwThreadAffinityMask); 

         可以通過函數SetThreaIdealProcessor來設置線程的理想CPU(儘可能運行在該CPU):

        DWORD SetThreaIdealProcessor(HANDLE hThread,DWORD dwIdealProcessor);       
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章