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