Linux核心搶占實現機制分析

2021-07-04 03:40:28 字數 4835 閱讀 4510

2.6新的可搶占式核心是指核心搶占,

即當程序位於核心空間時,有乙個更高優先順序的任務出現時,如果當前核心允許搶占,則可以將當前任務掛起,執行優先順序更高的程序。

在2.5.4

版本之前,

linux

核心是不可搶占的,高優先順序的程序不能中止正在核心中執行的低優先順序的程序而搶占

cpu執行。程序一旦處於核心態

(例如使用者程序執行系統呼叫

),則除非程序自願放棄

cpu,否則該程序將一直執行下去,直至完成或退出核心。與此相反,乙個可搶占的

linux

核心可以讓

linux

核心如同使用者空間一樣允許被搶占。當乙個高優先順序的程序到達時,不管當前程序處於使用者態還是核心態,如果當前允許搶占,可搶占核心的

linux

都會排程高優先順序的程序執行。

核心即將返回使用者空間的時候,如果need resched

標誌被設定,會導致

schedule()

被呼叫,此時就會發生使用者搶占。

在核心返回使用者空間的時候,它知道自己是安全的。所以,核心無論是在從中斷處理程式還是在系統呼叫後返回,都會檢查need resched

標誌。如果它被設定了,那麼,核心會選擇乙個其他

(更合適的

)程序投入執行。

簡而言之,使用者搶占在以下情況時產生:

l從系統調返回使用者空間。

l從中斷處理程式返回使用者空間。

在不支援核心搶占的核心中,核心**可以一直執行,到它完成為止。也就是說,排程程式沒有辦法在乙個核心級的任務正在執行的時候重新排程—

核心中的各任務是協作方式排程的,不具備搶占性。當然,

執行於核心態 的程序可以主動放棄cpu

,比如,在系統呼叫服務例程中,由於核心**由於等待資源而放棄cpu

,這種情況叫做計畫性程序切換(

planned process switch

)。核心**一直要執行到完成

(返回使用者空間

)或明顯的阻塞為止,

在單cpu

情況下,這樣的設定大大簡化了核心的同步和保護機制

。可以分兩步對此加以分析:

首先,不考慮程序在核心中自願放棄cpu

的情況(

也即在核心中不發生程序的切換

)。乙個程序一旦進入核心就將一直執行下去,直到完成或退出核心。在其沒有完成或退出核心之前,不會有另外乙個程序進入核心,即程序在核心中的執行是序列的,不可能有多個程序同時在核心中執行,這樣核心**設計時就不用考慮多個程序同時執行所帶來的併發問題。

linux

的核心開發人員就不用考慮複雜的程序併發執行互斥訪問臨界資源的問題。當程序在訪問、修改核心的資料結構時就不需要加鎖來防止多個程序同時進入臨界區。這時只需再考慮一下中斷的情況,若有中斷處理例程也有可能訪問程序正在訪問的資料結構,那麼程序只要在進入臨界區前先進行關中斷操作,退出臨界區時進行開中斷操作就可以了。

再考慮一下程序自願放棄cpu

的情況。因為對

cpu的放棄是自願的、主動的,也就意味著程序在核心中的切換是預先知道的,不會出現在不知道的情況下發生程序的切換。這樣就只需在發生程序切換的地方考慮一下多個程序同時執行所可能帶來的併發問題,而不必在整個核心範圍內都要考慮程序併發執行問題。

實現核心的可搶占對linux

具有重要意義。

首先,這是將linux

應用於實時系統所必需的。

實時系統對響應時間有嚴格的限定,當乙個實時程序被實時裝置的硬體中斷喚醒後,它應在限定的時間內被排程執行。而linux

不能滿足這一要求,因為

linux

的核心是不可搶占的,不能確定系統在核心中的停留時間。事實上當核心首席執行官的系統呼叫時,實時程序要等到核心中執行的程序退出核心才能被排程,由此產生的響應延遲,在如今的硬體條件下,會長達

100ms級。

這對於那些要求高實時響應的系統是不能接受的。而可搶占的核心不僅對linux

的實時應用至關重要,而且能解決

linux

對多**

(video, audio)

等要求低延遲的應用支援不夠好的缺陷。

由於可搶占核心的重要性,在linux2.5.4

版本發布時,可搶占被併入核心,同

smp一樣作為核心的一項標準可選配置。

有幾種情況linux

核心不應該被搶占,除此之外

linux

核心在任意一點都可被搶占。這幾種情況是:

(1)核心正進行中斷處理。在linux

核心中程序不能搶占中斷

(中斷只能被其他中斷中止、搶占,程序不能中止、搶占中斷

),在中斷例程中不允許進行程序排程。程序排程函式

schedule()

會對此作出判斷,如果是在中斷中呼叫,會列印出錯資訊。

(2)核心正在進行中斷上下文的bottom half(

中斷的

半部)

處理。

硬體中斷返回前會執行軟中斷,此時仍然處於中斷上下文中。

(3)核心的**段正持有spinlock

自旋鎖、

writelock/readlock

讀寫鎖等鎖,處乾這些鎖的保護狀態中。

核心中的這些鎖是為了在smp

系統中短時間內保證不同

cpu上執行的程序併發執行的正確性。當持有這些鎖時,核心不應該被搶占,否則由於搶占將導致其他

cpu長期不能獲得鎖而死等。

(4)核心正在執行排程程式scheduler

搶占的原因就是為了進行新的排程,沒有理由將排程程式搶占掉再執行排程程式。

(5)核心正在對每個cpu「私有」

的資料結構操作

(per-cpu date structures)

。在smp

中,對於

per-cpu

資料結構未用

spinlocks

保護,因為這些資料結構隱含地被保護了

(不同的

cpu有不一樣的

per-cpu

資料,其他

cpu上執行的程序不會用到另乙個

cpu的

per-cpu資料)

。但是如果允許搶占,但乙個程序被搶占後重新排程,有可能排程到其他的

cpu上去,這時定義的

per-cpu

變數就會有問題,這時應禁搶占。

為保證linux

核心在以上情況下不會被搶占,搶占式核心使用了乙個變數

preempt_ count

,稱為核心搶占鎖。這一變數被設定在程序的

pcb結構

task_struct

中。每當核心要進入以上幾種狀態時,變數

preempt_ count就加1

,指示核心不允許搶占。每當核心從以上幾種狀態退出時,變數

preempt_ count就減1

,同時進行可搶占的判斷與排程。

從中斷返回核心空間的時候,核心會檢查need_resched

和preempt_count

的值。如果

need_ resched

被設定,並且

preempt count為0

的話,這說明可能有乙個更為重要的任務需要執行並且可以安全地搶占,此時,排程程式就會被呼叫。如果

preempt-count不為0

,則說明核心現在處乾不可搶占狀態,不能進行重新排程。這時,就會像通常那樣直接從中斷返回當前執行程序。如果當前程序持有的所有的鎖都被釋放了,那麼

preempt_ count

就會重新為

0。此時,釋放鎖的**會檢查

need_ resched

是否被設定。如果是的話,就會呼叫排程程式。

在2.6

版的核心中,核心引入了搶占能力;現在,只要重新排程是安全的,那麼核心就可以在任何時間搶占正在執行的任務。

那麼,什麼時候重新排程才是安全的呢?

只要premptcount為0

,核心就可以進行搶占。通常鎖和中斷是非搶占區域的標誌。

由於核心是支援smp

的,所以,如果沒有持有鎖,那麼正在執行的**就是可重新導人的,也就是可以搶占的。

如果核心中的程序被阻塞了,或它顯式地呼叫了schedule()

,核心搶占也會顯式地發生。這種形式的核心搶占從來都是受支援的

(實際上是主動讓出

cpu)

,因為根本無需額外的邏輯來保證核心可以安全地被搶占。如果**顯式的呼叫了

schedule()

,那麼它應該清楚自己是可以安全地被搶占的。

核心搶占可能發生在:

l 當從中斷處理程式正在執行,

且返回核心空間之前。 l 

當核心**再一次具有可搶占性的時候,如解鎖及使能軟中斷(local_bh_enable)等。

l 如果核心中的任務顯式的呼叫schedule() l 

如果核心中的任務阻塞(

這同樣也會導致呼叫

schedule())

Linux核心搶占機制 preempt

早期的linux核心 2.5.4版本之前 是不可搶占的。它的排程方法是 乙個程序可以通過schedule 函式自願地啟動一次排程。非自願的強制性排程只能發生在 每次從系統呼叫返回的前夕以及每次從中斷或異常處理返回到使用者空間的前夕。但是,如果在系統空間發生中斷或異常是不會引起排程的。這種方式使核心實...

Linux 核心搶占

核心搶占 kernel preemption 是一種有效的降低系統響應延時的方法。在核心裡,有三個相關的配置選項。顧名思義,不開啟核心搶占。這是很多伺服器的預設配置選項。在沒有開啟核心搶占的時候,程序的排程時機僅僅發生在非常有限的幾處 程序自己主動觸發排程,例如 通過sleep schedule y...

Linux核心 了解Linux核心搶占

目錄 無強制搶占 可搶占核心 自願核心搶占 完全實時搶占 在配置linux核心時,我們可以設定一些影響系統行為的引數。您可以使用不同的優先順序,排程類和搶占模型。了解並選擇正確的引數非常重要。在這篇文章中,我將介紹不同的搶占模型,以及每種模型如何影響使用者和核心行為 如果配置核心 使用make me...