日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线程操作函数

發布時間:2024/7/19 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程操作函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程的掛起和恢復

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

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

SuspendThread??ResumeThread?都返回之前的掛起計數。

一個線程最多可以掛起MAXIMUM_SUSPEND_COUNT?(WinNT.h中定義為127次)。

?

進程的掛起和恢復

對于Windows來說,不存在暫停或恢復進程的概念,因為進程從來不會被安排獲得cpu時間。

但是我們可以創建一個函數,用來掛起或者恢復進程中的全部線程,這樣就能掛起或者恢復一個進程了。

參考代碼如下:

#include <Windows.h>

#include <stdio.h>

#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。

轉載于:https://www.cnblogs.com/fwycmengsoft/p/6158130.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的线程操作函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。