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