日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

线程调度优先级和关联性

發(fā)布時(shí)間:2025/3/15 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程调度优先级和关联性 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

每個(gè)現(xiàn)場(chǎng)都有一個(gè)上下文。后者保存在線(xiàn)程的內(nèi)核對(duì)象中。這上下文反應(yīng)了線(xiàn)程上一次執(zhí)行時(shí)CPU寄存器的狀態(tài),大約每隔20ms(GetSystemTimeAdjustment函數(shù)第二個(gè)參數(shù)的返回值),windows都會(huì)查看所有當(dāng)前存在的線(xiàn)程內(nèi)核對(duì)象,在這些對(duì)象中,只有一些被認(rèn)為是可以調(diào)度的,windows在可調(diào)度的線(xiàn)程內(nèi)核對(duì)象中選擇一個(gè),并將上次保存在線(xiàn)程上下文中的值載入CPU寄存器,這一操作被稱(chēng)為上下文切換。

在縣城初始化之后,CreateProcess或者CreateThread函數(shù)將查看是否有CREATE_SUSPENDED標(biāo)志傳入,如果有,函數(shù)會(huì)返回并讓新線(xiàn)程處于掛起狀態(tài)。如果沒(méi)有函數(shù)將線(xiàn)程的掛起計(jì)數(shù)遞減為0,當(dāng)線(xiàn)程的掛起計(jì)數(shù)為0時(shí),線(xiàn)程就成為可調(diào)度的,除非還在等待某個(gè)事件 的發(fā)生。通過(guò)創(chuàng)建一個(gè)處于掛起狀態(tài)的線(xiàn)程,我們可以通過(guò)ResumeThread來(lái)恢復(fù)線(xiàn)程。同樣也有SuspendThread可以?huà)炱鹁€(xiàn)程。

線(xiàn)程可以告訴系統(tǒng)要休眠,調(diào)用Sleep函數(shù)

1.調(diào)用Sleep函數(shù)將使得線(xiàn)程資源放棄屬于他的時(shí)間片中剩下的部分

2.系統(tǒng)設(shè)置線(xiàn)程不可調(diào)度的時(shí)間只是近似于所設(shè)定的毫秒數(shù),windows不是實(shí)時(shí)操作系統(tǒng),線(xiàn)程實(shí)際醒來(lái)的情況取決于系統(tǒng)中其他線(xiàn)程的運(yùn)行情況

3.可以調(diào)用Sleep函數(shù)并給dwms參數(shù)傳入INFINITE,這是在告訴系統(tǒng),永遠(yuǎn)不要調(diào)度這進(jìn)程

4.Sleep(0),這是在告訴系統(tǒng),主調(diào)線(xiàn)程放棄了時(shí)間片的剩余部分,它強(qiáng)制系統(tǒng)調(diào)度其他線(xiàn)程,但是系統(tǒng)有可能重新調(diào)低剛剛調(diào)用了sleep(0)的線(xiàn)程,如果沒(méi)有相同或者較高優(yōu)先級(jí)的可調(diào)度線(xiàn)程時(shí),就會(huì)發(fā)生這樣的情況。

切換到另一個(gè)線(xiàn)程

系統(tǒng)提供了一個(gè)名為SwitchToThread的函數(shù),如果存在另一個(gè)可調(diào)度的線(xiàn)程,那么系統(tǒng)會(huì)讓此線(xiàn)程運(yùn)行。

Bool SwitchToThread();

調(diào)用這函數(shù)時(shí),系統(tǒng)查看是否存在正急需CPU時(shí)間的饑餓線(xiàn)程,如果沒(méi)有,函數(shù)立即返回,如果存在,則調(diào)度該線(xiàn)程(其優(yōu)先級(jí)可能比SwitchToThread的主調(diào)線(xiàn)程低),饑餓線(xiàn)程運(yùn)行一個(gè)時(shí)間量,然后系統(tǒng)調(diào)度程序回復(fù)正常運(yùn)行。

通過(guò)調(diào)用SwitcgToThread和調(diào)用Sleep(0)類(lèi)似,區(qū)別在于SwitchToThread運(yùn)行執(zhí)行較低優(yōu)先級(jí)的線(xiàn)程。

線(xiàn)程的執(zhí)行時(shí)間

有時(shí)候我們需要計(jì)算一個(gè)線(xiàn)程執(zhí)行某項(xiàng)任務(wù)需要消耗多長(zhǎng)時(shí)間,關(guān)于這一點(diǎn),可以利用GetTickCount64();

但是有一個(gè)前提就是代碼的執(zhí)行不會(huì)被中斷,可是在搶占式的操作系統(tǒng),這樣是比較困難的。

BOOL WINAPI GetThreadTimes(_In_ HANDLE hThread,//需要獲取cpu時(shí)間的線(xiàn)程句柄_Out_ LPFILETIME lpCreationTime,//創(chuàng)建時(shí)間_Out_ LPFILETIME lpExitTime,//退出時(shí)間_Out_ LPFILETIME lpKernelTime,//內(nèi)核時(shí)間_Out_ LPFILETIME lpUserTime//用戶(hù)時(shí)間 );

同樣的也有GetProcessTimes,可以用于進(jìn)程中的所有線(xiàn)程。

BOOL WINAPI GetProcessTimes( __in HANDLE hProcess, __out LPFILETIME lpCreationTime, __out LPFILETIME lpExitTime, __out LPFILETIME lpKernelTime, __out LPFILETIME lpUserTime ); hProcess:為需要獲取相關(guān)時(shí)間的進(jìn)程句柄
lpCreationTime:進(jìn)程的創(chuàng)建時(shí)間
lpExitTime:進(jìn)程的退出時(shí)間
lpKernelTime:進(jìn)程在內(nèi)核模式下的所有時(shí)間
lpUserTime:進(jìn)程在用戶(hù)模式下的所有時(shí)間
BOOL QueryPerformanceFrequency(LARGE_INTEGER *pliFrequency) BOOL QueryPerformanceCounter(LARGE_INTEGER *pliCount);

這兩個(gè)函數(shù)假設(shè)正在執(zhí)行的線(xiàn)程不會(huì)被搶占。它們都是針對(duì)生命期很短的代碼塊。GetCPUFrequencyInMHZ可以獲得cpu頻率。

在windows定義的所有數(shù)據(jù)結(jié)構(gòu)中,CONTEXT結(jié)構(gòu)是唯一一個(gè)依賴(lài)于cpu的。我們可以通過(guò)調(diào)用GetThreadContext來(lái)獲得當(dāng)期cpu寄存器的狀態(tài)。

BOOL GetThreadContext(HANDLE hThread, LPCONTEXT lpContext);

hThread:獲取信息目標(biāo)進(jìn)程的線(xiàn)程句柄。(用OpenThread獲取)
lpContext:一個(gè)用于接收信息的CONTEXT結(jié)構(gòu)指針
返回值:如果成功,返回值不為零,如果不成功,返回值為零,若想看其他的錯(cuò)誤信息,參考GetLastError

第二個(gè)參數(shù)是CONTEXT結(jié)構(gòu)指針。在分配CONTEXT結(jié)構(gòu)后,需要初始化ContextFlag標(biāo)志,表示以表示要獲取哪些寄存器。函數(shù)執(zhí)行后CONTEXT對(duì)象中就填入我們請(qǐng)求的成員。

ContextFlag可以是:

CONTEXT_CONTROL表示控制寄存器。
CONTEXT_INTEGER表示整數(shù)寄存器。
CONTEXT_FLOAT?表示浮點(diǎn)寄存器。
CONTEXT_ALL?表示CONTEXT_CONTROL?|CONTEXT_INTEGER|CONTEXT_SEGMENTS。

?在調(diào)用GetThreadContext時(shí),需要先調(diào)用SuspendThread。因?yàn)樵谡{(diào)用GetThreadContext時(shí)系統(tǒng)可能正在執(zhí)行那個(gè)線(xiàn)程,此時(shí)線(xiàn)程的上下文與獲得的信息就不一致了。注意,它只能返回線(xiàn)程的用戶(hù)模式上下文。如果當(dāng)調(diào)用SuspendThread時(shí)線(xiàn)程正在內(nèi)核模式運(yùn)行,線(xiàn)程不會(huì)暫停,直到其返回用戶(hù)空間。但是返回到用戶(hù)控件后不會(huì)執(zhí)行任何用戶(hù)模式代碼。

不僅僅能獲得線(xiàn)程的進(jìn)程上下文,我們還可以設(shè)置它。這可以調(diào)用:

?BOOL SetThreadContext( HANDLE hThread,CONST CONTEXT *pContext);

GetThreadContext和SetThreadContext函數(shù)為我們提供了對(duì)線(xiàn)程許多控制的方法,但是需要小心使用。

線(xiàn)程優(yōu)先級(jí)

前面提到的調(diào)度程序在調(diào)度另外一個(gè)線(xiàn)程之前,可以運(yùn)行一個(gè)線(xiàn)程大約20ms的時(shí)間。但是這是所有優(yōu)先級(jí)都相同的情況。實(shí)際上系統(tǒng)中的很多線(xiàn)程優(yōu)先級(jí)是不同的,這將影響調(diào)度程序如何選擇下一個(gè)要運(yùn)行的線(xiàn)程。

Windows的線(xiàn)程優(yōu)先級(jí)從0到31。每個(gè)線(xiàn)程都會(huì)分配一個(gè)優(yōu)先級(jí)。當(dāng)系統(tǒng)確定給哪個(gè)線(xiàn)程分配cpu時(shí),它會(huì)首先查看優(yōu)先級(jí)為31的線(xiàn)程,直至所有優(yōu)先級(jí)為31的線(xiàn)程都被調(diào)度。然后再查看下一優(yōu)先級(jí)線(xiàn)程。只要存在優(yōu)先級(jí)為31的線(xiàn)程,系統(tǒng)就不會(huì)調(diào)度0-30級(jí)的線(xiàn)程。低優(yōu)先級(jí)線(xiàn)程長(zhǎng)時(shí)間得不到cpu時(shí)間,這被稱(chēng)為饑餓。這不經(jīng)常出現(xiàn),因?yàn)榇蠖鄶?shù)線(xiàn)程都是不可調(diào)度的。

系統(tǒng)啟動(dòng)時(shí)會(huì)創(chuàng)建一個(gè)優(yōu)先級(jí)為0的idle線(xiàn)程,整個(gè)系統(tǒng)只有它的優(yōu)先級(jí)為0。它在系統(tǒng)中沒(méi)有其他線(xiàn)程運(yùn)行時(shí)將系統(tǒng)內(nèi)存中所有閑置頁(yè)面清0。

Windows中的線(xiàn)程優(yōu)先級(jí)是由優(yōu)先級(jí)類(lèi)和相對(duì)線(xiàn)程優(yōu)先級(jí)來(lái)確定的。系統(tǒng)通過(guò)線(xiàn)程的相對(duì)優(yōu)先級(jí)加上線(xiàn)程所屬進(jìn)程的優(yōu)先級(jí)來(lái)確定線(xiàn)程的優(yōu)先級(jí)值。這個(gè)值被稱(chēng)為線(xiàn)程的基本優(yōu)先級(jí)值。

Windows支持6個(gè)進(jìn)程優(yōu)先級(jí)類(lèi):idle?,below?normal?,normal?,above?normal,high和real-time。它們是相對(duì)與進(jìn)程的。Normal最為常用,為99%的進(jìn)程使用。

idle優(yōu)先級(jí)類(lèi)在系統(tǒng)什么都不做的時(shí)候運(yùn)行的應(yīng)用程序。如屏幕保護(hù)程序。real-time優(yōu)先級(jí)類(lèi)優(yōu)先級(jí)別最高,但是沒(méi)有開(kāi)放給用戶(hù)使用。因?yàn)榇藘?yōu)先級(jí)類(lèi)的程序會(huì)影響操作系統(tǒng)的任務(wù)。

Windows支持7個(gè)相對(duì)線(xiàn)程優(yōu)先級(jí):idle,lowest?,below?normal,normal,above?normal,highest和time-critical。這些優(yōu)先級(jí)是相對(duì)于進(jìn)程優(yōu)先級(jí)的。大多數(shù)的線(xiàn)程使用normal優(yōu)先級(jí)。

概括起來(lái)就是進(jìn)程屬于某個(gè)優(yōu)先級(jí)類(lèi),另外還可以指定進(jìn)程中線(xiàn)程的相對(duì)線(xiàn)程優(yōu)先級(jí)。也就是說(shuō)線(xiàn)程優(yōu)先級(jí)是相對(duì)于進(jìn)程優(yōu)先級(jí)的。time-critical優(yōu)先級(jí)對(duì)于real-time優(yōu)先級(jí)類(lèi),優(yōu)先級(jí)為31。相對(duì)于其他優(yōu)先級(jí)類(lèi)則為15。需要注意的是進(jìn)程優(yōu)先級(jí)是抽象的概念,因?yàn)檫M(jìn)程并不參與調(diào)度。
在優(yōu)先級(jí)編程時(shí),首先需要在調(diào)用CreateProcess時(shí)可以再fdwCreate參數(shù)中傳入想要的優(yōu)先級(jí)。fdwCreate可以是以下標(biāo)識(shí)符:
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

進(jìn)程運(yùn)行后可以調(diào)用SetPrioritClass來(lái)改變進(jìn)程優(yōu)先級(jí)類(lèi)。

BOOL SetPriorityClass(HANDLE hProcess,DWORD fdwPriority);

可以調(diào)用GetPriorityClass來(lái)獲得進(jìn)程的優(yōu)先級(jí)類(lèi)。DWORD?GetPriorityClass(HANDLE?hProcess);
上面是指定的進(jìn)程優(yōu)先級(jí)類(lèi),調(diào)用CreateThread創(chuàng)建線(xiàn)程時(shí),它的線(xiàn)程優(yōu)先級(jí)總是被設(shè)置為normal.

關(guān)聯(lián)性
????默認(rèn)情況下,windows在分配cpu時(shí)采用軟關(guān)聯(lián)的方式。也就是說(shuō)在其他因素相同的情況下,系統(tǒng)使線(xiàn)程在上一次運(yùn)行的處理器上運(yùn)行。這有助于重用仍在處理器高速緩存中的數(shù)據(jù)。
系統(tǒng)在啟動(dòng)時(shí)確定cpu數(shù)量。應(yīng)用程序可以通過(guò)調(diào)用GetSysInfo來(lái)查詢(xún)cpu的數(shù)量。如果需要限制一個(gè)進(jìn)程的所有線(xiàn)程在某些cpu上運(yùn)行,可以調(diào)用:

BOOL SetProcessAffinityMask( HANDLE hProcess,DWORD_PTR dwProcessAffinityMask); 第一個(gè)參數(shù)代表要設(shè)置的進(jìn)程句柄。
第二參數(shù)是一個(gè)位掩碼。代表線(xiàn)程可以在哪些cpu上運(yùn)行。
注意子進(jìn)程將繼承父進(jìn)程的關(guān)聯(lián)性。
GetProcessAffinityMask返回進(jìn)程的關(guān)聯(lián)掩碼。
相應(yīng)的還可以設(shè)置某個(gè)線(xiàn)程只在一組cpu上運(yùn)行:
SetThreadAffinityMask。
有時(shí)候強(qiáng)制一個(gè)線(xiàn)程只在某個(gè)特定的cpu上運(yùn)行并不是什么好主意。Windows允許一個(gè)線(xiàn)程運(yùn)行在一個(gè)cpu上,但如果需要,它將被移動(dòng)到一個(gè)空閑的cpu上。
要給線(xiàn)程設(shè)置一個(gè)理想的cpu,可以調(diào)用:
DWORD SetThreadIdealProcessro(HANDLE hThread,DWORD dwIdealProcessor); dwIdealProcessor是一個(gè)0到31/63之間的整數(shù)。表示線(xiàn)程希望設(shè)置的cpu。可以傳入MAXIMUM_PROCESSOR值,表示沒(méi)有理想的cpu。











總結(jié)

以上是生活随笔為你收集整理的线程调度优先级和关联性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。