|
|
aoface (stranger) 06-09-25 19:55
|
關(guān)于進(jìn)程切換內(nèi)核搶占概念的不解,請各位指教 | |
最近學(xué)OS,有一處不明,特發(fā)貼請教一下壇里的兄弟姐妹:)
首先有幾句話是課本上的:
1.內(nèi)核態(tài)運行的進(jìn)程是不可以被搶占的。 2.只有下列三種情況可以發(fā)生進(jìn)程切換: (1)進(jìn)程進(jìn)入等待態(tài)
(2)中斷返回但此時進(jìn)程不是最具備有CPU的資格 (3)系統(tǒng)調(diào)用返回但此時進(jìn)程不是最具備有CPU的資格
[請問1.上述的(2)(3)情況中,是不是在核心態(tài)運行的進(jìn)程被調(diào)度出CPU了?那么是否和第1條沖突?
2.(2)(3)所指是否是時間片到達(dá)被迫退出CPU呢?
3.我描述一個流程,大家看一下對不對。一個用戶態(tài)進(jìn)程運行著,時鐘中斷來了,進(jìn)入核心態(tài)(請問此時進(jìn)程是處于核心態(tài)運行嗎?如果不是,不過不知如何描述進(jìn)程這時的狀態(tài)),轉(zhuǎn)向時鐘中斷處理程序,發(fā)現(xiàn)這個進(jìn)程的時間片到了,于是要把它請出CPU到就緒狀態(tài),這個時候發(fā)生的是進(jìn)程切換沒錯吧,此時調(diào)度一個新進(jìn)程到運行態(tài),此時是不是同時也返回了用戶態(tài)呢?
]
一口氣問了這么多,希望能有大俠指點一二,謝謝。
|
Iambitious (stranger) 06-09-26 09:47
|
Re:
關(guān)于進(jìn)程切換內(nèi)核搶占概念的不解,請各位指教 | |
linux是支持內(nèi)核搶占的。(編譯內(nèi)核的時候選擇搶占模式) linux分為兩種搶占: 1.用戶搶占:
發(fā)生在系統(tǒng)調(diào)用返回,和中斷返回的時候。 2.內(nèi)核搶占: 發(fā)生在中斷返回,顯式調(diào)用schedule()。
你所說的那種情況對應(yīng)的是用戶搶占。
用戶進(jìn)程與內(nèi)核進(jìn)程是完全不同的,一個用戶進(jìn)程是通過系統(tǒng)調(diào)用來調(diào)用內(nèi)核的函數(shù),而內(nèi)核進(jìn)程是本身執(zhí)行一個內(nèi)核函數(shù),內(nèi)核進(jìn)程永遠(yuǎn)不會被換出內(nèi)核空間。
|
aoface (stranger) 06-09-26 17:47
|
Re:
關(guān)于進(jìn)程切換內(nèi)核搶占概念的不解,請各位指教 | |
謝謝樓上的回答。此外還有個問題想問問:一個進(jìn)程處于核心態(tài)運行下被中斷打斷了,此時的進(jìn)程處于什么狀態(tài)?(沒有發(fā)生進(jìn)程切換)
|
leviathan (addict) 06-09-27 10:45
|
Re:
關(guān)于進(jìn)程切換內(nèi)核搶占概念的不解,請各位指教 | |
處理中斷的時候, 被打斷的進(jìn)程還是RUNNING態(tài)。
中斷處理不改變被打斷進(jìn)程的狀態(tài)的,只有在處理完畢中斷,要返回的時候,如果發(fā)生重新調(diào)度, 才可能改變進(jìn)程狀態(tài)。
|
huihuizxc (stranger) 06-09-27 14:51
|
Re:
關(guān)于進(jìn)程切換內(nèi)核搶占概念的不解,請各位指教 | |
下面是自己對有些原代碼的分析
分析四 LINUX進(jìn)程調(diào)度
對于一些頻繁要執(zhí)行的代碼 效率非常的重要,
1、每個進(jìn)程在task_struct中和調(diào)度有關(guān)的保存信息: • policy
將被應(yīng)用于本進(jìn)程的調(diào)度策略。有兩種Linux進(jìn)程:普通的和實時的。實時進(jìn)程擁有比其他進(jìn)程都要高的優(yōu)先級。如果有一個實時進(jìn)程準(zhǔn)備好了運行,它總是先運行。實時進(jìn)程可以有兩種高度策略:“輪轉(zhuǎn)(round
robin)”法和“先進(jìn)先出(first in first
out)”。在輪轉(zhuǎn)法調(diào)度中每個可運行的實時進(jìn)程依次運行;而在先進(jìn)先出法中,實時進(jìn)程按它們進(jìn)入運行隊列的順序依次運行,并且該順序永不會改變。
• nice
調(diào)度器將給予進(jìn)程的優(yōu)先級。它也是進(jìn)程被允許運行時可以運行的時間量(在jiffies中)。可以通過系統(tǒng)調(diào)用的方法和renice命令來改變進(jìn)程的優(yōu)先級。
• rt_priority
Linux支持實時進(jìn)程,并且它們在調(diào)度時擁有比系統(tǒng)中其他非實時進(jìn)程更高的優(yōu)先級。這個字段使調(diào)度器可以給每個實時進(jìn)程一個相對優(yōu)先級。實時進(jìn)程的優(yōu)先級
可以用系統(tǒng)調(diào)用改變。 • counter
此進(jìn)程允許的運行時間量(在jiffies中)在第一次運行時被置成nice的值,然后在每個時鐘“滴答”中遞減。 •
need_resched 告訴調(diào)度器是否應(yīng)該進(jìn)行調(diào)度了。在以下幾種情況下會被設(shè)置成1,一時鐘中斷中發(fā)現(xiàn)當(dāng)前進(jìn)程的時間片已經(jīng)用完,二從系統(tǒng)返回當(dāng)用戶空間的時候
處于禮讓,改變調(diào)度策略或者有優(yōu)先級別更加高的進(jìn)程被喚醒(比當(dāng)前進(jìn)程),三是一個進(jìn)程改變調(diào)度策略和禮讓
2、調(diào)度策略:
1>、總體上繼承了UNIX以優(yōu)先級為基礎(chǔ)的調(diào)度。即每個進(jìn)程有一個代表運行資格的權(quán)值,然后系統(tǒng)挑選權(quán)值最高的進(jìn)程投入運行。在運行過程中,當(dāng)前進(jìn)程的資格隨時間而遞減(在時鐘中斷中),這樣一來在下次的調(diào)度中那些權(quán)值低的可能比當(dāng)前運行的要高了,從而得到了運行的可能。如果在中間沒有出現(xiàn)調(diào)度(強制引起的一些調(diào)度,比如中斷),那么等到它的權(quán)值為0時(時間片用光了),系統(tǒng)就會進(jìn)行一次調(diào)度。如果所有可運行進(jìn)程的權(quán)值都是0那么系統(tǒng)將進(jìn)行一次進(jìn)程運行資格的重新計算,資格的計算主要是以優(yōu)先級為基礎(chǔ)。
2>、局部上又分為3種調(diào)度策略,也可以說是2種實時和非實時 非實時 SCHED_OTHER:普通進(jìn)程 適合交互式分時進(jìn)程。
實時 SCHED_RR SCHED_FIFO: SCHED_FIFO:
一旦調(diào)度中被選種,它會一直運行,直到自愿讓出CPU為止,如果進(jìn)程運行時間比較短,那沒什么問題,如果運行時間比較長,那么處于同優(yōu)先級的進(jìn)程將會一直等待,根本就沒機會得到運行。所以說這種調(diào)度策略適用于
時間性要求比較強,但是 每次運行時間比較段的進(jìn)程,比如對于一個外設(shè)的read數(shù)據(jù),需要時間性要求要快,但是執(zhí)行比較短。
SCHED_RR:采用輪流,可以說是補充了FIFO的同優(yōu)先級進(jìn)程得不到運行的情況,對于這種調(diào)度,當(dāng)時間片用完時,會把當(dāng)前進(jìn)程放到進(jìn)程等待隊列末尾,那么同優(yōu)先級別的進(jìn)程就得到了運行的機會了。
非實時進(jìn)程的權(quán)值確定: 剩余的時間配額 + (20 - p->nice),其中nice是UNIX沿用下來的負(fù)向優(yōu)先級,取值返回是 19~
-20,以-20為最高,所以經(jīng)過轉(zhuǎn)換以后是1到40
40為最高。如果是內(nèi)核線程或者用戶空間與當(dāng)前進(jìn)程相同而不需要切換用戶空間,那么會得到+1的獎勵。要注意的是當(dāng)剩余的時間配額為0的時候 進(jìn)程的權(quán)值被強制設(shè)置成0,這樣系統(tǒng)就可以進(jìn)行調(diào)度了,上面已經(jīng)提到如果全部就緒的進(jìn)程權(quán)值為0那么就要進(jìn)行重新計算,重新計算包括了那些未就緒的進(jìn)程 計算公式
p->counter = (p->counter>>1) +
NICE_TO_TICKS(p->nice),這樣對于未就緒的非實時進(jìn)程得到了提升優(yōu)先級別的機會,當(dāng)然對于實時進(jìn)程的優(yōu)先級別是沒有影響的。但明顯可以看出無論這么提升最終也是不會達(dá)到NICE_TO_TICKS(p->nice)的2陪的。
實時進(jìn)程的權(quán)值確定 1000+p->rt_priority,其中1000是基數(shù),rt_priority(rt就是real
time的意思)即實時進(jìn)程的優(yōu)先級,而時間配額p->counter的當(dāng)前值對實時進(jìn)程不起作。對于SCHED_RR,當(dāng)p->counter為0的時候會把當(dāng)前進(jìn)程放到隊列的末尾,nice對實時進(jìn)程的權(quán)值也是沒有影響的,但是對于SCHED_RR的時間配額大小有關(guān)系,因為時間配額的大小是根據(jù)p->counter
= (p->counter>>1) + NICE_TO_TICKS(p->nice)
計算的。而對于SCHED_FIFO本身就無所謂時間配額(因為即時間片用完了,當(dāng)前進(jìn)程的位置還是不變,仍舊在首位),除非有高優(yōu)先級的進(jìn)程,否則也不會退讓,所以都無關(guān)。
實時進(jìn)程比非實時進(jìn)程有著高很多的優(yōu)先級,在調(diào)度過程中,如果有實時進(jìn)程準(zhǔn)備就緒,那么非實時進(jìn)程根本就得不到運行的機會。 這里需要補充的一點是
如果在調(diào)度是發(fā)現(xiàn)有2個或者以上的進(jìn)程具有相同的優(yōu)先級,那么就調(diào)用先進(jìn)入的那個進(jìn)程。
3、調(diào)度方式: 分為2種,自愿調(diào)度和強制性調(diào)度。
1>、自愿調(diào)度就是調(diào)用函數(shù)schedule(),隨時都可以發(fā)生,這個函數(shù)是在系統(tǒng)空間調(diào)用的,在應(yīng)用空間可以用pause()得到同樣的效果。
還有二種情況
一是是禮讓,調(diào)用函數(shù)sched_yield()。具體方法是:將current->policy中的SCHED_YIELD標(biāo)志置為1,然后把need_resched設(shè)置成表示要進(jìn)行調(diào)度。在調(diào)度過程中會把SCHED_YIELD這個標(biāo)志清楚為0。使用sched_yield()的情況一般就是等待一個事件的到來,但又不想使自己進(jìn)入睡眠狀態(tài),比如等待執(zhí)行一個IO的完畢,或者等待一個標(biāo)志位的到來等。禮讓不改變當(dāng)前進(jìn)程在可執(zhí)行進(jìn)程隊列中的位置,所以如果當(dāng)前進(jìn)程本身的優(yōu)先級別是很高很高的
比如是實時進(jìn)程,那么調(diào)度后運行的還是當(dāng)前進(jìn)程,這樣就失去了意義,所以說使用禮讓的進(jìn)程基本上要other調(diào)度的進(jìn)程(普通進(jìn)程)。
二是改變調(diào)度策略和參數(shù)系統(tǒng),函數(shù)是sched_setscheduler()的作用是改變進(jìn)程的調(diào)度策略。上面2中情況發(fā)生調(diào)度的的必要條件也是
從系統(tǒng)空間返回到用戶空間的前夕。
2>、強制調(diào)度,發(fā)生在從系統(tǒng)空間返回到用戶空間的前夕,但是有條件的,所以說是有條件的剝奪。比如說下面的情況:當(dāng)喚醒一個進(jìn)程,發(fā)現(xiàn)這個進(jìn)程的優(yōu)先級比當(dāng)前的要高,那么就會出現(xiàn)一次調(diào)度。
還有一種情況就是發(fā)生在時鐘中斷里面,當(dāng)檢查到到前進(jìn)程運行時間過長的時候發(fā)生,前面已經(jīng)提到。
這里需要提到一點強制調(diào)度是有條件的,也就是必須發(fā)生在從系統(tǒng)空間返回到用戶空間的前夕。比如打個比方:進(jìn)程調(diào)用一個內(nèi)核函數(shù)處于內(nèi)核態(tài)時,這個時候產(chǎn)生了一個中斷,而此時系統(tǒng)已經(jīng)知道這個進(jìn)行的時間片已經(jīng)用完,中斷服務(wù)程序執(zhí)行完畢后返回,因為返回后還是處于內(nèi)核態(tài),所以此時是不會發(fā)生調(diào)度的,那么在什么時候發(fā)生調(diào)度呢?要等到進(jìn)程調(diào)用的內(nèi)核函數(shù)返回。也就是必須發(fā)生在從系統(tǒng)空間返回到用戶空間的前夕,這樣一來就存在一個問題,如果這個時候一個高優(yōu)先級別的進(jìn)程在等待,將會被延遲響應(yīng)(在搶占式調(diào)度中沒這個現(xiàn)象)。
4、搶占調(diào)度: Linux 2。6下支持搶占調(diào)度,原理是
如果內(nèi)核不是在一個中斷處理程序中,并且不在spinlock保護(hù)的代碼中,就認(rèn)為可以 安全 的進(jìn)行進(jìn)程切換。 實際上他在不可搶占的linux的基礎(chǔ)上做了2件事情
在釋放spinlock時候或者當(dāng)中斷返回時,如果當(dāng)前執(zhí)行的進(jìn)程的need_resched被標(biāo)記(需要調(diào)度),則進(jìn)行搶占式調(diào)度。
具體可以看進(jìn)程調(diào)度原理相關(guān)部分代碼: 函數(shù)Schedule() kernel/sched.c
|
aoface (stranger) 06-09-30 10:11
|
Re:
關(guān)于進(jìn)程切換內(nèi)核搶占概念的不解,請各位指教 | |
謝謝大家的指教,學(xué)習(xí)了。
|