三 核心可搶占以及可搶占和可中斷的區別
四 搶占
五 中斷
搶占是核心對程序的管理:當高優先順序的任務因中斷而成為就緒,特定的低優先順序程序將讓出cpu,而那個高優先順序的程序得到cpu。 可以這樣(簡單地)說,中斷是因為硬體,而搶占是因為中斷帶來特定事件的發生。
一般來說,cpu在任何時刻都處於以下三種情況之一:
(1) 執行於使用者空間,執行使用者程序;
(2) 執行於核心空間,處於程序上下文;
(3) 執行於核心空間,處於中斷上下文。
應用程式通過系統呼叫陷入核心,此時處於程序上下文
。現代幾乎所有的cpu體系結構都支援中斷。當外部裝置產生中斷,向cpu傳送乙個非同步訊號,cpu呼叫相應的中斷處理程式來處理該中斷,此時cpu處於中斷上下文
。
在程序上下文
中,可以通過current關聯相應的任務。程序以程序上下文的形式執行在核心空間,可以發生睡眠,所以在程序上下文中,可以使用訊號量(semaphore)。實際上,核心經常在程序上下文中使用訊號量來完成任務之間的同步,當然也可以使用鎖。
中斷上下文
不屬於任何程序,它與current沒有任何關係(儘管此時current指向被中斷的程序)。由於沒有程序背景,在中斷上下文中不能發生睡眠,否則又如何對它進行排程。所以在中斷上下文中只能使用鎖進行同步,正是因為這個原因,中斷上下文也叫做原子上下文(atomic context)(關於同步可以參考同步)。在中斷處理程式中,通常會禁止同一中斷,甚至會禁止整個本地中斷,所以中斷處理程式應該盡可能迅速,所以又把中斷處理分成上部和下部(關於中斷)。
上下文切換,也就是從乙個可執行程序切換到另乙個可執行程序。上下文切換由函式context_switch()函式完成,該函式位於kernel/sched.c中,它由程序排程函式schedule()呼叫。
static
inline
task_t *
context_switch
(runqueue_t *rq, task_t *prev, task_t *next)
else
switch_mm
(oldmm, mm, next);if
(unlikely
(!prev->mm)
)/* here we just switch the register state and the stack. */
switch_to
(prev, next, prev)
;return prev;
}
其中,switch_mm()將虛擬記憶體對映到新的程序;switch_to完成最終的程序切換,它儲存原程序的所有暫存器資訊,恢復新程序的所有暫存器資訊,並執行新的程序。無論何時,核心想要進行任務切換,都通過呼叫schedule()完成任務切換。
首先被中斷不是被搶占,中斷和搶占是兩個概念。
搶占必須涉及程序上下文的切換,而中斷是在中斷上下文。
所謂可搶占搶的是程序上下文,人人都爭取上台。
可中斷指的是是否可以中斷當前cpu而進入我的中斷處理函式。
如果核心是不可搶占的(比如說2.4的核心),一旦切進核心態,只要**不是主動釋放cpu它就可以一直佔著cpu。雖不可搶占,但若此時發生中斷,**還是要交出cpu,但是中斷返回之後,**又能霸佔cpu了,此為可中斷但不可搶占
。
如果核心是可搶占的(比如2.6或之後的核心),上述情況就不會發生了。
搶占也分使用者搶占和核心搶占。詳解請參考搶占。
當核心即將返回使用者空間時,核心會檢查need_resched是否設定,如果設定,則呼叫schedule(),此時,發生使用者搶占。一般來說,使用者搶占發生幾下情況:
(1) 從系統呼叫返回使用者空間
;
(2) 從中斷(異常)處理程式返回使用者空間
。
核心從2.6開始就支援核心搶占,對於非核心搶占系統,核心**可以一直執行,直到完成,也就是說當程序處於核心態時,是不能被搶占的(當然,執行於核心態的程序可以主動放棄cpu,比如,在系統呼叫服務例程中,由於核心**由於等待資源而放棄cpu,這種情況叫做計畫性程序切換(planned process switch))
。但是,對於由非同步事件(比如中斷)引起的程序切換,搶占式核心與非搶占式是有區別的,對於前者叫做強制性程序切換(forced process switch)。
為了支援核心搶占,核心引入了preempt_count欄位,該計數初始值為0,每當使用鎖時加1,釋放鎖時減1。當preempt_count為0時,表示核心可以被安全的搶占,大於0時,則禁止核心搶占。
當從中斷返回核心空間時,核心會檢preempt_count和need_resched的值(返回使用者空間時只需要檢查need_resched)
,如查preempt_count為0且need_resched設定,則呼叫schedule(),完成任務搶占。
一般來說,核心搶占發生以下情況:
當乙個中斷處理例程退出,在返回到核心態時。preempt_count為0且need_resched置位。這是隱式的呼叫schedule()函式。
當核心**再一次具有可搶占性的時候,如解鎖(spin_unlock_bh)及使能軟中斷(local_bh_enable)等,此時當preempt_count從正整數變為0時。這也是隱式的呼叫schedule()函式
如果核心中的任務顯式的呼叫schedule(), 任務主動放棄cpu使用權。
如果核心中的任務阻塞(這同樣也會導致呼叫schedule())。任務主動放棄cpu使用權。
詳細可參考中斷
中斷方式分為同步中斷和非同步中斷
。同步中斷是由cpu控制單元產生的,「同步」是指只有在一條指令執行完畢後,cpu才會發出中斷,而不是發生在**指令執行期間,比如系統呼叫。而非同步中斷是由其他硬體裝置依照cpu時鐘訊號產生的,即意味著中斷能夠在指令之間發生,例如鍵盤中斷。有乙個知識點值得了解:核心態能夠觸發的唯一異常就是缺頁異常,其他的都是使用者態觸發的。
中斷過程分為上下兩個部分:中斷上半部、下半部。
上半部處理緊要事情。下半部處理不那麼要緊的任務。比如:網絡卡上來的資料推進協議棧,然後推給上層應用程式。
當前的核心有三種下半部的實現方式:softirq、tasklet、working queue。
名稱上下文
特點概述
softirq
中斷上下文
可中斷不可睡眠
速度最快。同乙個softirq可能會同時執行在多個核上,必須非常小心的處理資料同步
tasklet
中斷上下文
可中斷不可睡眠
基於softirq實現,同一類的tasklet不會被同時執行,程式設計代價小
working quere
程序上下文
可中斷可睡眠
基於核心執行緒實現
搶占式核心與非搶占式核心的區別
核心搶占 可搶占式核心 即當程序位於核心空間時,有乙個更高優先順序的任務出現時,如果當前核心允許搶占,則可以將當前任務掛起,執行優先順序更高的程序。非搶占式核心 高優先順序的程序不能中止正在核心中執行的低優先順序的程序而搶占cpu執行。程序一旦處於核心態 例如使用者程序執行系統呼叫 則除非程序自願放...
核心搶占VS使用者搶占
使用者搶占 核心即將返回使用者空間的時候,如果need resched被設定,會導致schedule 被呼叫,此時就會發生使用者搶占。在核心返回使用者空間的時候,它知道自己是安全的,因為既然它可以繼續去執行當前程序,那麼它當然可以再去選擇乙個新的程序去執行。所以核心無論是從中斷處理程式還是在系統呼叫...
核心搶占和低延遲
2.8.3 核心搶占和低延遲相關工作 2 如果可以搶占,則需要執行下列步驟 kernel sched.c do while unlikely test thread flag tif need resched 在呼叫排程器之前,搶占計數器的值設定為preempt active。這設定了搶占計數器中的...