線程操做函數

線程的掛起和恢復

DWORD SuspendThread ( HANDLE hThread );   //掛起線程函數

DWORD ResumeThread ( HANDLE hThread );   //恢復線程spa

SuspendThread  ResumeThread 都返回以前的掛起計數。操作系統

一個線程最多能夠掛起MAXIMUM_SUSPEND_COUNT (WinNT.h中定義爲127次)。線程

 

進程的掛起和恢復

對於Windows來講,不存在暫停或恢復進程的概念,由於進程歷來不會被安排得到cpu時間。指針

可是咱們能夠建立一個函數,用來掛起或者恢復進程中的所有線程,這樣就能掛起或者恢復一個進程了。調試

參考代碼以下:對象

#include <Windows.h>進程

#include <stdio.h>ip

#include <Tlhelp32.h>內存

//dwProcessID參數爲須要掛起或者恢復的進程ID

// bSuspend參數若是爲TRUE就掛起進程,不然恢復進程

void SuspendProcess(DWORD dwProcessID, BOOL bSuspend)

{

         HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID);                    //得到系統內因此線程

         if (hSnapshot != INVALID_HANDLE_VALUE)

         {

                   THREADENTRY32 te;

                   ZeroMemory(&te, sizeof(te));

                   te.dwSize = sizeof(te);

 

                   BOOL bOK = Thread32First(hSnapshot, &te);  

                   for (; bOK; bOK = Thread32Next(hSnapshot, &te))

                   {

                            if (te.th32OwnerProcessID == dwProcessID)          //必須制定,不然程序會嘗試掛起系統內全部的線程,就會致使死機

                            {

                                     HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);

                                     if (hThread != NULL)

                                     {

                                               if (bSuspend)

                                               {

                                                        SuspendThread(hThread);

                                               }

                                               else

                                                        ResumeThread(hThread);

                                     }

                                     CloseHandle(hThread);

                            }

                   }

         }

         CloseHandle(hSnapshot);

}

int main(void)

{

         SuspendProcess(9636, FALSE);

         return 0;

}

 

睡眠

VOID Sleep (DWORD dwMilliseconds);

這個函數將使線程本身掛起 dwMilliseconds 長的時間。

1.       調用Sleep,可以使線程自願放棄它剩餘的時間片。

2. 系統將在大約的指定毫秒數內使線程不可調度。不錯,若是告訴系統,想睡眠 100ms,那麼能夠睡眠大約這麼長時間,可是也可能睡眠數秒鐘或者數分鐘。記住,Windows不是個實時操做系統。雖然線程可能在規定的時間被喚醒,可是它可否作到,取決於系統中還有什麼操做正在進行。

3.能夠調用Sleep,而且爲dwMilliseconds參數傳遞INFINITE。這將告訴系統永遠不要調度該線程。這不是一件值得去作的事情。最好是讓線程退出,並還原它的堆棧和內核對象。

4. 能夠將0傳遞給Sleep。這將告訴系統,調用線程將釋放剩餘的時間片,並迫使系統調度另外一個線程。可是,系統能夠對剛剛調用 Sleep的線程從新調度。Sleep(0)是指CPU交出當前線程的執行權,讓CPU去執行其餘線程。也就是放棄當前線程的時間片,轉而執行其餘線程

 

切換到另外一個線程

BOOL SwitchToThread (void);

當調用這個函數的時候,系統要查看是否存在一個迫切須要CPU時間的線程。若是沒有線程迫切須要CPU時間,SwitchToThread就會當即返回。若是存在一個迫切須要 CPU時間的線程,SwitchToThread就對該線程進行調度(該線程的優先級可能低於調用 SwitchToThread的線程)。

這個迫切須要CPU時間的線程能夠運行一個時間段,而後系統調度程序照常運行。該函數容許一個須要資源的線程強制另外一個優先級較低、而目前卻擁有該資源的線程放棄該資源。若是調用 SwitchToThread函數時沒有其餘線程可以運行,那麼該函數返回 FALSE,不然返回一個非0值。

Sleep():時間片只能讓給優先級相同或更高的線程;

SwitchToThread():只要有可調度線程,即使優先級較低,也會讓其調度。

 

在實際上下文中談CONTEXT結構

CONTEXT結構包括如下部分:

   CONTEXT_CONTROL:包含CPU的控制寄存器,好比指今指針,堆棧指針,標誌和函數返回地址..AX, BX, CX, DX, SI, D
     CONTEXT_INTEGER:用於標識CPU的整數寄存器.DS, ES, FS, GS
   CONTEXT_FLOATING_POINT:用於標識CPU的浮點寄存器.
     CONTEXT_SEGMENTS:用於標識CPU的段寄存器.SS:SP, CS:IP, FLAGS, BP
   CONTEXT_DEBUG_REGISTER:用於標識CPU的調試寄存器.  
   CONTEXT_EXTENDED_REGISTERS:用於標識CPU的擴展寄存器I
   CONTEXT_FULL:至關於CONTEXT_CONTROL or CONTEXT_INTEGER or   CONTEXT_SEGMENTS,即這三個標誌的組合

 

 

咱們可使用GetThreadContext函數來查看線程內核對象的內部,並獲取當前CPU寄存器狀態的集合。

BOOL GetThreadContext (

HANDLE  hThread,

PCONTEXT  pContext)

若要調用該函數,只需指定一個CONTEXT結構,對某些標誌(該結構的ContextFlags成員)進行初始化,指明想要收回哪些寄存器,並將該結構的地址傳遞給GetThreadContext 。而後該函數將數據填入你要求的成員。

在調用GetThreadContext函數以前,應該調用SuspendThread,不然,線程可能恰好被調度,這樣一來,線程的上下文就和所獲取的信息不一致了。

示例代碼以下: 

         CONTEXT Context;                  //定義一個CONTEXT結構

 

         Context.ContextFlags = CONTEXT_CONTROL;    //告訴系統咱們想獲取線程控制寄存器的內容   

         GetThreadContext(hThread, &Context);      //調用GetThreadContext獲取相關信息

Ps:在調用GetThreadContext函數以前,必須首先初始化CONTEXT結構的ContextFlags成員。

要得到線程的全部重要的寄存器(也就是微軟認爲最經常使用的寄存器),應該像下面同樣初始化ContextFlags:

Context.ContextFlags = CONTEXT_FULL;

WinNT. h頭文件中,定義了CONTEXT_FULLCONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS

 

固然,咱們還能夠經過調用SetThreadContext函數來改變結構中的成員,並把新的寄存器值放回線程的內核對象中

BOOL SetThreadContext (

HANDLE  hThread,

CONST CONTEXT  *pContext)

一樣,若是要改變哪一個線程的上下文,應該先暫停該線程。       

         CONTEXT Context;      //定義一個CONTEXT結構      

         SuspendThread(hThread);  //掛起線程  

         Context.ContextFlags = CONTEXT_CONTROL;   //獲取當前上下文的值

         GetThreadContext(hThread, &Context);

 

         Context.Eip = 0x00010000;      //Eip字段存儲的是指令指針,如今讓指令指針指向地址 0x00010000;

         Context.ContextFlags = CONTEXT_CONTROL;

 

         SetThreadContext(hThread, &Context);   //從新設置線程上下文

 

         ResumeThread(hThread);         //恢復線程,如今線程開始從0x00010000這個地方開始執行指令

 

線程的優先級

優先級爲0的線程:系統啓動時,會建立一個優先級爲0的「頁面清零線程」,它只有在系統中沒有其餘可調度線程時,才能調度,用來清除內存中的閒置頁面。

優先級在1 ~ 15之間的線程:通常用戶模式下,線程的優先級都在該範圍。

優先級在16 ~ 30之間的線程:通常是內核線程。

 

一旦進程運行,即可以經過調用SetPriorityClass來改變本身的優先級

BOOL SetPriorityClass(

         HANDLE  hProcess

         DWORD  fdwPriority);

用來獲取進程優先級:

DWORD GetPriorityClass( HANDLE  hProcess );

 

設置和獲取線程的相對優先級:

BOOL SetThreadPriority (

         HANDLE  hThread,

         Int  nPriority);

Int GetThreadPriority(HANDLE  hThread);

 

容許或者禁止進程或者線程動態提高本身的優先級:

BOOL SetProcessPriorityBoost(

         HANDLE  hProcess,

         BOOL  bDisablePriorityBoost);

 BOOL SetThreadPriorityBoost(

         HANDLE  hThread,

         BOOL  bDisablePriorityBoost);

 

判斷當前是否是啓用優先級提高:

BOOL GetProcessPriorityBoost(

         HANDLE  hProcess,

         PBOOL  pbDisablePriorityBoost);

 BOOL GetThreadPriorityBoost(

         HANDLE  hThread,

         PBOOL  pbDisablePriorityBoost);

 

在多CPU的狀況下,咱們能夠限制某些線程只在可用的cpu的一個子集上運行:

BOOL SetProcessAffinityMask(

         HANDLE  hProcess

         DWORD_PTR  dwProcessAffinityMask);

第一個參數hProcess表明要設置的進程。第二個參數dwProcessAffinityMask是一個位掩碼,表明線程能夠在哪些CPU上運行。例如,傳入0x00000005意味着這個進程中的線程能夠在CPU 0 和 CPU 2上運行,可是不能在CPU 1 和 CPU 3~31上運行。

 

獲取進程的關聯性掩碼:

BOOL GetProcessAffinityMask(

         HANDLE  hProcess

         PDWORD_PTR  pdwProcessAffinityMask,

PDWORD_PTR  pdwSystemAffinityMask);

設置線程的關聯性掩碼:

BOOL SetThreadAffinityMask(

         HANDLE  hThread

         DWORD_PTR  dwThreadAffinityMask);

 

有時候強制一個線程只是用特定的某個CPU並非什麼好主意。例如,若是有三個線程都只能使用CPU0,而CPU1,CPU2和CPU3卻無所事事。咱們想讓一個線程運行在一個CPU上,可是同時系統也容許他移到另外一個空閒的CPU,那就更好了。要給線程設置一個理想的CPU,能夠調用以下:

DWORD SetThreadIdealProcessor(

         HANDLE  hThread,

         DWORD  dwIdealProcessor);

hThread用於指明要爲哪一個線程設置首選CPU。

dwIdealProcessor函數不是個位掩碼,它是個從0到31/63,用於指明供線程但願使用的首選CPU 。能夠傳遞一個MAXIMUM_PROCESSORS的值(在WinNT.h中定義,在32位操做系統中定義爲32,64位操做系統中定義爲64),代表線程沒有理想的CPU。若是沒有爲該線程設置理想的CPU,那麼該函數返回前一個理想的CPU或MAXIMUM_PROCESSORS。

相關文章
相關標籤/搜索