自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入分析Linux內(nèi)核源碼-進(jìn)程調(diào)度(2)

系統(tǒng) Linux
調(diào)度的實(shí)質(zhì)就是資源的分配。系統(tǒng)通過(guò)不同的調(diào)度算法(Scheduling Algorithm)來(lái)實(shí)現(xiàn)這種資源的分配。通常來(lái)說(shuō),選擇什么樣的調(diào)度算法取決于的資源分配的策略(Scheduling Policy),在這里只說(shuō)明與Linux調(diào)度相關(guān)的幾種算法及這些算法的原理。

3 Linux的調(diào)度程序-Schedule( )

3.1基本原理

調(diào)度的實(shí)質(zhì)就是資源的分配。系統(tǒng)通過(guò)不同的調(diào)度算法(Scheduling Algorithm)來(lái)實(shí)現(xiàn)這種資源的分配。通常來(lái)說(shuō),選擇什么樣的調(diào)度算法取決于的資源分配的策略(Scheduling Policy),在這里只說(shuō)明與Linux調(diào)度相關(guān)的幾種算法及這些算法的原理。

一個(gè)好的調(diào)度算法應(yīng)當(dāng)考慮以下幾個(gè)方面:

(1)公平:保證每個(gè)進(jìn)程得到合理的CPU時(shí)間。

(2)高效:使CPU保持忙碌狀態(tài),即總是有進(jìn)程在CPU上運(yùn)行。

(3)響應(yīng)時(shí)間:使交互用戶的響應(yīng)時(shí)間盡可能短。

(4)周轉(zhuǎn)時(shí)間:使批處理用戶等待輸出的時(shí)間盡可能短。

(5)吞吐量:使單位時(shí)間內(nèi)處理的進(jìn)程數(shù)量盡可能多。

很顯然,這5個(gè)目標(biāo)不可能同時(shí)達(dá)到,所以,不同的操作系統(tǒng)會(huì)在這幾個(gè)方面中作出相應(yīng)的取舍,從而確定自己的調(diào)度算法,例如UNIX采用動(dòng)態(tài)優(yōu)先數(shù)調(diào)度、BSD采用多級(jí)反饋隊(duì)列調(diào)度、Windows采用搶先多任務(wù)調(diào)度等等。

下面來(lái)了解一下主要的調(diào)度算法及其基本原理:

1.時(shí)間片輪轉(zhuǎn)調(diào)度算法

時(shí)間片(Time Slice)就是分配給進(jìn)程運(yùn)行的一段時(shí)間。在通常的輪轉(zhuǎn)法中,系統(tǒng)將所有的可運(yùn)行(即就緒)進(jìn)程按先來(lái)先服務(wù)的原則,排成一個(gè)隊(duì)列,每次調(diào)度時(shí)把CPU分配給隊(duì)首進(jìn)程,并令其執(zhí)行一個(gè)時(shí)間片。當(dāng)執(zhí)行的時(shí)間片用完時(shí),系統(tǒng)發(fā)出信號(hào),通知調(diào)度程序,調(diào)度程序便據(jù)此信號(hào)來(lái)停止該進(jìn)程的執(zhí)行,并將它送到運(yùn)行隊(duì)列的末尾,等待下一次執(zhí)行;然后,把處理機(jī)分配給就緒隊(duì)列中新的隊(duì)首進(jìn)程,同時(shí)也讓它執(zhí)行一個(gè)時(shí)間片。這樣就可以保證運(yùn)行隊(duì)列中的所有進(jìn)程,在一個(gè)給定的時(shí)間內(nèi),均能獲得一時(shí)間片的處理機(jī)執(zhí)行時(shí)間。

2.優(yōu)先權(quán)調(diào)度算法

為了照顧到緊迫型進(jìn)程在進(jìn)入系統(tǒng)后便能獲得優(yōu)先處理,引入了***優(yōu)先權(quán)調(diào)度算法。當(dāng)將該算法用于進(jìn)程調(diào)度時(shí),系統(tǒng)將把處理機(jī)分配給運(yùn)行隊(duì)列中優(yōu)先權(quán)***的進(jìn)程,這時(shí),又可進(jìn)一步把該算法分成兩種方式:

(1) 非搶占式優(yōu)先權(quán)算法(又稱(chēng)不可剝奪調(diào)度:Nonpreemptive Scheduling)

在這種方式下,系統(tǒng)一旦將處理機(jī)(CPU)分配給運(yùn)行隊(duì)列中優(yōu)先權(quán)***的進(jìn)程后,該進(jìn)程便一直執(zhí)行下去,直至完成;或因發(fā)生某事件使該進(jìn)程放棄處理機(jī)時(shí),系統(tǒng)方可將處理機(jī)分配給另一個(gè)優(yōu)先權(quán)高的進(jìn)程。這種調(diào)度算法主要用于批處理系統(tǒng)中,也可用于某些對(duì)實(shí)時(shí)性要求不嚴(yán)的實(shí)時(shí)系統(tǒng)中。

(2) 搶占式優(yōu)先權(quán)調(diào)度算法(又稱(chēng)可剝奪調(diào)度:Preemptive Scheduling)

該算法的本質(zhì)就是系統(tǒng)中當(dāng)前運(yùn)行的進(jìn)程永遠(yuǎn)是可運(yùn)行進(jìn)程中優(yōu)先權(quán)***的那個(gè)。在采用這種調(diào)度算法時(shí),每當(dāng)出現(xiàn)一新的可運(yùn)行進(jìn)程,就將它和當(dāng)前運(yùn)行進(jìn)程進(jìn)行優(yōu)先權(quán)比較,如果高于當(dāng)前進(jìn)程,將觸發(fā)進(jìn)程調(diào)度。這種方式的優(yōu)先權(quán)調(diào)度算法,能更好的滿足緊迫進(jìn)程的要求,故而常用于要求比較嚴(yán)格的實(shí)時(shí)系統(tǒng)中,以及對(duì)性能要求較高的批處理和分時(shí)系統(tǒng)中。Linux也采用這種調(diào)度算法。

3.多級(jí)反饋隊(duì)列調(diào)度

這是時(shí)下最時(shí)髦的一種調(diào)度算法。其本質(zhì)是:綜合了時(shí)間片輪轉(zhuǎn)調(diào)度和搶占式優(yōu)先權(quán)調(diào)度的優(yōu)點(diǎn),即:優(yōu)先權(quán)高的進(jìn)程先運(yùn)行給定的時(shí)間片,相同優(yōu)先權(quán)的進(jìn)程輪流運(yùn)行給定的時(shí)間片。

4.實(shí)時(shí)調(diào)度

***我們來(lái)看一下實(shí)時(shí)系統(tǒng)中的調(diào)度。什么叫實(shí)時(shí)系統(tǒng),就是系統(tǒng)對(duì)外部事件有求必應(yīng)、盡快響應(yīng)。在實(shí)時(shí)系統(tǒng)中,廣泛采用搶占調(diào)度方式,特別是對(duì)于那些要求嚴(yán)格的實(shí)時(shí)系統(tǒng)。因?yàn)檫@種調(diào)度方式既具有較大的靈活性,又能獲得很小的調(diào)度延遲;但是這種調(diào)度方式也比較復(fù)雜。

3.2 Linux進(jìn)程調(diào)度時(shí)機(jī)

Linux的調(diào)度程序是一個(gè)叫Schedule()的函數(shù),這個(gè)函數(shù)被調(diào)用的頻率很高,由它來(lái)決定是否要進(jìn)行進(jìn)程的切換,如果要切換的話,切換到哪個(gè)進(jìn)程等等。我們先來(lái)看在什么情況下要執(zhí)行調(diào)度程序,我們把這種情況叫做調(diào)度時(shí)機(jī)。

Linux調(diào)度時(shí)機(jī)主要有:

1、進(jìn)程狀態(tài)轉(zhuǎn)換的時(shí)刻:進(jìn)程終止、進(jìn)程睡眠;

2、當(dāng)前進(jìn)程的時(shí)間片用完時(shí)(current->counter=0);

3、設(shè)備驅(qū)動(dòng)程序主動(dòng)調(diào)用schedule;

4、進(jìn)程從中斷、異常及系統(tǒng)調(diào)用返回到用戶態(tài)時(shí);

時(shí)機(jī)1,進(jìn)程要調(diào)用sleep()或exit()等函數(shù)進(jìn)行狀態(tài)轉(zhuǎn)換,這些函數(shù)會(huì)主動(dòng)調(diào)用調(diào)度程序進(jìn)行進(jìn)程調(diào)度;

時(shí)機(jī)2,由于進(jìn)程的時(shí)間片是由時(shí)鐘中斷來(lái)更新的,因此,這種情況和時(shí)機(jī)4是一樣的。

#p#

時(shí)機(jī)3,當(dāng)設(shè)備驅(qū)動(dòng)程序執(zhí)行長(zhǎng)而重復(fù)的任務(wù)時(shí),直接調(diào)用調(diào)度程序。在每次反復(fù)循環(huán)中,驅(qū)動(dòng)程序都檢查need_resched的值,如果必要,則調(diào)用調(diào)度程序schedule()主動(dòng)放棄CPU。

時(shí)機(jī)4,如前所述,不管是從中斷、異常還是系統(tǒng)調(diào)用返回,最終都調(diào)用ret_from_sys_call(),由這個(gè)函數(shù)進(jìn)行調(diào)度標(biāo)志的檢測(cè),如果必要,則調(diào)用調(diào)度程序。那么,為什么從系統(tǒng)調(diào)用返回時(shí)要調(diào)用調(diào)度程序呢?這當(dāng)然是從效率考慮。從系統(tǒng)調(diào)用返回意味著要離開(kāi)內(nèi)核態(tài)而返回到用戶態(tài),而狀態(tài)的轉(zhuǎn)換要花費(fèi)一定的時(shí)間,因此,在返回到用戶態(tài)前,系統(tǒng)把在內(nèi)核態(tài)該處理的事全部做完。

每個(gè)時(shí)鐘中斷(timer interrupt)發(fā)生時(shí),由三個(gè)函數(shù)協(xié)同工作,共同完成進(jìn)程的選擇和切換,它們是:schedule()、do_timer()及ret_form_sys_call()。我們先來(lái)解釋一下這三個(gè)函數(shù):

schedule():進(jìn)程調(diào)度函數(shù),由它來(lái)完成進(jìn)程的選擇(調(diào)度);

do_timer():暫且稱(chēng)之為時(shí)鐘函數(shù),該函數(shù)在時(shí)鐘中斷服務(wù)程序中被調(diào)用,被調(diào)用的頻率就是時(shí)鐘中斷的頻率即每秒鐘100次(簡(jiǎn)稱(chēng)100赫茲或100Hz);

ret_from_sys_call():系統(tǒng)調(diào)用返回函數(shù)。當(dāng)一個(gè)系統(tǒng)調(diào)用或中斷完成時(shí),該函數(shù)被調(diào)用,用于處理一些收尾工作,例如信號(hào)處理、核心任務(wù)等等。

這三個(gè)函數(shù)是如何協(xié)調(diào)工作的呢?

前面我們看到,時(shí)鐘中斷是一個(gè)中斷服務(wù)程序,它的主要組成部分就是時(shí)鐘函數(shù)do_timer(),由這個(gè)函數(shù)完成系統(tǒng)時(shí)間的更新、進(jìn)程時(shí)間片的更新等工作,更新后的進(jìn)程時(shí)間片counter作為調(diào)度的主要依據(jù)。在時(shí)鐘中斷返回時(shí),要調(diào)用函數(shù)ret_from_sys_call(),前面我們已經(jīng)討論過(guò)這個(gè)函數(shù),在這個(gè)函數(shù)中有如下幾行:

cmpl $0, _need_resched

jne reschedule

……

restore_all:

RESTORE_ALL

reschedule:

call SYMBOL_NAME(schedule)

jmp ret_from_sys_call

這幾行的意思很明顯:檢測(cè) need_resched 標(biāo)志,如果此標(biāo)志為非0,那么就轉(zhuǎn)到reschedule處調(diào)用調(diào)度程序schedule()進(jìn)行進(jìn)程的選擇。調(diào)度程序schedule()會(huì)根據(jù)具體的標(biāo)準(zhǔn)在運(yùn)行隊(duì)列中選擇下一個(gè)應(yīng)該運(yùn)行的進(jìn)程。當(dāng)從調(diào)度程序返回時(shí),如果發(fā)現(xiàn)又有調(diào)度標(biāo)志被設(shè)置,則又調(diào)用調(diào)度程序,直到調(diào)度標(biāo)志為0,這時(shí),從調(diào)度程序返回時(shí)由RESTORE_ALL恢復(fù)被選定進(jìn)程的環(huán)境,返回到被選定進(jìn)程的用戶空間,使之得到運(yùn)行。

Linux 調(diào)度程序和其他的UNIX調(diào)度程序不同,尤其是在“nice level”優(yōu)先級(jí)的處理上,與優(yōu)先權(quán)調(diào)度(priority高的進(jìn)程***運(yùn)行)不同,Linux用的是時(shí)間片輪轉(zhuǎn)調(diào)度(Round Robing),但同時(shí)又保證了高優(yōu)先級(jí)的進(jìn)程運(yùn)行的既快、時(shí)間又長(zhǎng)(both sooner and longer)。而標(biāo)準(zhǔn)的UNIX調(diào)度程序都用到了多級(jí)進(jìn)程隊(duì)列。大多數(shù)的實(shí)現(xiàn)都用到了二級(jí)優(yōu)先隊(duì)列:一個(gè)標(biāo)準(zhǔn)隊(duì)列和一個(gè)實(shí)時(shí)(“real time”)隊(duì)列。一般情況下,如果實(shí)時(shí)隊(duì)列中的進(jìn)程未被阻塞,它們都要在標(biāo)準(zhǔn)隊(duì)列中的進(jìn)程之前被執(zhí)行,并且,每個(gè)隊(duì)列中,“nice level”高的進(jìn)程先被執(zhí)行。

3.3 進(jìn)程調(diào)度的依據(jù)

調(diào)度程序運(yùn)行時(shí),要在所有處于可運(yùn)行狀態(tài)的進(jìn)程之中選擇最值得運(yùn)行的進(jìn)程投入運(yùn)行。選擇進(jìn)程的依據(jù)是什么呢?在每個(gè)進(jìn)程的task_struct結(jié)構(gòu)中有這么五項(xiàng):

need_resched、nice、counter、policy 及rt_priority

need_resched: 在調(diào)度時(shí)機(jī)到來(lái)時(shí),檢測(cè)這個(gè)域的值,如果為1,則調(diào)用schedule() 。

counter: 進(jìn)程處于運(yùn)行狀態(tài)時(shí)所剩余的時(shí)鐘滴答數(shù),每次時(shí)鐘中斷到來(lái)時(shí),這個(gè)值就減1。當(dāng)這個(gè)域的值變得越來(lái)越小,直至為0時(shí),就把need_resched 域置1,因此,也把這個(gè)域叫做進(jìn)程的“動(dòng)態(tài)優(yōu)先級(jí)”。

nice: 進(jìn)程的“靜態(tài)優(yōu)先級(jí)”,這個(gè)域決定counter 的初值。只有通過(guò)nice(), sched_setparam()系統(tǒng)調(diào)用才能改變進(jìn)程的靜態(tài)優(yōu)先級(jí)。

rt_priority: 實(shí)時(shí)進(jìn)程的優(yōu)先級(jí)

policy: 從整體上區(qū)分實(shí)時(shí)進(jìn)程和普通進(jìn)程,因?yàn)閷?shí)時(shí)進(jìn)程和普通進(jìn)程的調(diào)度是不同的,它們兩者之間,實(shí)時(shí)進(jìn)程應(yīng)該先于普通進(jìn)程而運(yùn)行,可以通過(guò)系統(tǒng)調(diào)用sched_setscheduler( )來(lái)改變調(diào)度的策略。對(duì)于同一類(lèi)型的不同進(jìn)程,采用不同的標(biāo)準(zhǔn)來(lái)選擇進(jìn)程。對(duì)于普通進(jìn)程,選擇進(jìn)程的主要依據(jù)為counter和nice 。對(duì)于實(shí)時(shí)進(jìn)程,Linux采用了兩種調(diào)度策略,即FIFO(先來(lái)先服務(wù)調(diào)度)和RR(時(shí)間片輪轉(zhuǎn)調(diào)度)。因?yàn)閷?shí)時(shí)進(jìn)程具有一定程度的緊迫性,所以衡量一個(gè)實(shí)時(shí)進(jìn)程是否應(yīng)該運(yùn)行,Linux采用了一個(gè)比較固定的標(biāo)準(zhǔn)。實(shí)時(shí)進(jìn)程的counter只是用來(lái)表示該進(jìn)程的剩余滴答數(shù),并不作為衡量它是否值得運(yùn)行的標(biāo)準(zhǔn),這和普通進(jìn)程是有區(qū)別的。

3.4 進(jìn)程可運(yùn)行程度的衡量

函數(shù)goodness()就是用來(lái)衡量一個(gè)處于可運(yùn)行狀態(tài)的進(jìn)程值得運(yùn)行的程度。該函數(shù)綜合使用了上面我們提到的五項(xiàng),給每個(gè)處于可運(yùn)行狀態(tài)的進(jìn)程賦予一個(gè)權(quán)值(weight),調(diào)度程序以這個(gè)權(quán)值作為選擇進(jìn)程的唯一依據(jù)。函數(shù)主體如下:

static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm)

{     int weight;     /* 權(quán)值,作為衡量進(jìn)程是否運(yùn)行的唯一依據(jù) *

weight=-1;

if (p->policy&SCHED_YIELD)

goto out; /*如果該進(jìn)程愿意“禮讓?zhuān)▂ield)”,則讓其權(quán)值為-1 */

switch(p->policy)

{

/* 實(shí)時(shí)進(jìn)程*/

case SCHED_FIFO:

case SCHED_RR:

weight = 1000 + p->rt_priority;

/* 普通進(jìn)程 */

case SCHED_OTHER:

{     weight = p->counter;

if(!weight)

goto out

/* 做細(xì)微的調(diào)整*/

if (p->mm=this_mm||!p->mm)

weight = weight+1;

weight+=20-p->nice;       /*在剩余counter一樣的情況下,短進(jìn)程優(yōu)先*/

}

}

out:

return weight;   /*返回權(quán)值*/

}

其中,在sched.h中對(duì)調(diào)度策略定義如下:

#define SCHED_OTHER             0

#define SCHED_FIFO              1

#define SCHED_RR                2

#define SCHED_YIELD             0x10

這個(gè)函數(shù)比較很簡(jiǎn)單。首先,根據(jù)policy區(qū)分實(shí)時(shí)進(jìn)程和普通進(jìn)程。實(shí)時(shí)進(jìn)程的權(quán)值取決于其實(shí)時(shí)優(yōu)先級(jí),其至少是1000,與conter和nice無(wú)關(guān)。普通進(jìn)程的權(quán)值需特別說(shuō)明兩點(diǎn):

為什么進(jìn)行細(xì)微的調(diào)整?如果p->mm為空,則意味著該進(jìn)程無(wú)用戶空間(例如內(nèi)核線程),則無(wú)需切換到用戶空間。如果p->mm=this_mm,則說(shuō)明該進(jìn)程的用戶空間就是當(dāng)前進(jìn)程的用戶空間,該進(jìn)程完全有可能再次得到運(yùn)行。對(duì)于以上兩種情況,都給其權(quán)值加1,算是對(duì)它們小小的獎(jiǎng)勵(lì)。

進(jìn)程的優(yōu)先級(jí)nice是從早期Unix沿用下來(lái)的負(fù)向優(yōu)先級(jí),其數(shù)值標(biāo)志“謙讓”的程度,其值越大,就表示其越“謙讓”,也就是優(yōu)先級(jí)越低,其取值范圍為-20~+19,因此,(20-p->nice)的取值范圍就是0~40??梢钥闯觯胀ㄟM(jìn)程的權(quán)值不僅考慮了其剩余的時(shí)間片,還考慮了其優(yōu)先級(jí),優(yōu)先級(jí)越高,其權(quán)值越大。

根據(jù)進(jìn)程調(diào)度的依據(jù),調(diào)度程序就可以控制系統(tǒng)中的所有處于可運(yùn)行狀態(tài)的進(jìn)程并在它們之間進(jìn)行選擇。
 

【編輯推薦】

  1. 深入分析Linux內(nèi)核源碼-進(jìn)程調(diào)度(1)
  2. Linux下用gdb檢測(cè)內(nèi)核rootkit的方法
  3. Linux內(nèi)核中的DeviceMapper機(jī)制
責(zé)任編輯:趙寧寧 來(lái)源: chinaitlab
相關(guān)推薦

2009-12-11 09:42:54

Linux內(nèi)核源碼進(jìn)程調(diào)度

2021-12-15 15:03:51

Linux內(nèi)核調(diào)度

2010-03-08 14:53:48

Linux分區(qū)

2009-07-03 11:14:57

2023-05-08 12:03:14

Linux內(nèi)核進(jìn)程

2010-09-07 14:21:22

PPPoE協(xié)議

2022-04-12 08:30:45

TomcatWeb 應(yīng)用Servlet

2017-01-15 22:51:16

2020-11-12 18:08:05

JavaLinux多線程

2011-03-23 11:01:55

LAMP 架構(gòu)

2012-05-14 14:09:53

Linux內(nèi)核調(diào)度系統(tǒng)

2023-11-26 18:54:29

Linux調(diào)度器

2011-09-01 13:51:52

JavaScript

2023-02-01 08:13:30

Redis內(nèi)存碎片

2022-08-30 07:00:18

執(zhí)行引擎Hotspot虛擬機(jī)

2021-10-29 16:36:53

AMSAndroidActivityMan

2009-12-14 14:50:46

Ruby傳參數(shù)

2009-12-16 16:39:01

Visual Stud

2009-06-10 18:12:38

Equinox動(dòng)態(tài)化OSGi動(dòng)態(tài)化

2021-07-02 06:54:44

Linux內(nèi)核主調(diào)度器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)