對於什麽是實時系統,POSIX 1003.b作了這樣的定義:指系統能夠在限定的響應時間內提供所需水平的服務。而壹個由Donald Gillies提出的更加為大家接受的定義是:壹個實時系統是指計算的正確性不僅取決於程序的邏輯正確性,也取決於結果產生的時間,如果系統的時間約束條件得不到滿足,將會發生系統出錯。
實時系統根據其對於實時性要求的不同,可以分為軟實時和硬實時兩種類型。硬實時系統指系統要有確保的最壞情況下的服務時間,即對於事件的響應時間的截止期限是無論如何都必須得到滿足。比如航天中的宇宙飛船的控制等就是現實中這樣的系統。其他的所有有實時特性的系統都可以稱之為軟實時系統。如果明確地來說,軟實時系統就是那些從統計的角度來說,壹個任務(在下面的論述中,我們將對任務和進程不作區分)能夠得到有確保的處理時間,到達系統的事件也能夠在截止期限到來之前得到處理,但違反截止期限並不會帶來致命的錯誤,像實時多媒體系統就是壹種軟實時系統。
壹個計算機系統為了提供對於實時性的支持,它的操作系統必須對於CPU和其他資源進行有效的調度和管理。在多任務實時系統中,資源的調度和管理更加復雜。本文下面將先從分類的角度對各種實時任務調度算法進行討論,然後研究普通的 Linux操作系統的進程調度以及各種實時Linux系統為了支持實時特性對普通Linux系統所做的改進。最後分析了將Linux操作系統應用於實時領域中時所出現的壹些問題,並總結了各種實時Linux是如何解決這些問題的。
1. 實時CPU調度算法分類
各種實時操作系統的實時調度算法可以分為如下三種類別[Wang99][Gopalan01]:基於優先級的調度算法(Priority-driven scheduling-PD)、基於CPU使用比例的***享式的調度算法(Share-driven scheduling-SD)、以及基於時間的進程調度算法(Time-driven scheduling-TD),下面對這三種調度算法逐壹進行介紹。
1.1. 基於優先級的調度算法
基於優先級的調度算法給每個進程分配壹個優先級,在每次進程調度時,調度器總是調度那個具有最高優先級的任務來執行。根據不同的優先級分配方法,基於優先級的調度算法可以分為如下兩種類型[Krishna01][Wang99]:
靜態優先級調度算法:
這種調度算法給那些系統中得到運行的所有進程都靜態地分配壹個優先級。靜態優先級的分配可以根據應用的屬性來進行,比如任務的周期,用戶優先級,或者其它的預先確定的策略。RM(Rate-Monotonic)調度算法是壹種典型的靜態優先級調度算法,它根據任務的執行周期的長短來決定調度優先級,那些具有小的執行周期的任務具有較高的優先級。
動態優先級調度算法:
這種調度算法根據任務的資源需求來動態地分配任務的優先級,其目的就是在資源分配和調度時有更大的靈活性。非實時系統中就有很多這種調度算法,比如短作業優先的調度算法。在實時調度算法中, EDF算法是使用最多的壹種動態優先級調度算法,該算法給就緒隊列中的各個任務根據它們的截止期限(Deadline)來分配優先級,具有最近的截止期限的任務具有最高的優先級。
1.2. 基於比例***享調度算法
雖然基於優先級的調度算法簡單而有效,但這種調度算法提供的是壹種硬實時的調度,在很多情況下並不適合使用這種調度算法:比如象實時多媒體會議系統這樣的軟實時應用。對於這種軟實時應用,使用壹種比例***享式的資源調度算法(SD算法)更為適合。
比例***享調度算法指基於CPU使用比例的***享式的調度算法,其基本思想就是按照壹定的權重(比例)對壹組需要調度的任務進行調度,讓它們的執行時間與它們的權重完全成正比。
我們可以通過兩種方法來實現比例***享調度算法[Nieh01]:第壹種方法是調節各個就緒進程出現在調度隊列隊首的頻率,並調度隊首的進程執行;第二種做法就是逐次調度就緒隊列中的各個進程投入運行,但根據分配的權重調節分配個每個進程的運行時間片。
比例***享調度算法可以分為以下幾個類別:輪轉法、公平***享、公平隊列、彩票調度法(Lottery)等。
比例***享調度算法的壹個問題就是它沒有定義任何優先級的概念;所有的任務都根據它們申請的比例***享CPU資源,當系統處於過載狀態時,所有的任務的執行都會按比例地變慢。所以為了保證系統中實時進程能夠獲得壹定的CPU處理時間,壹般采用壹種動態調節進程權重的方法。
1.3. 基於時間的進程調度算法
對於那些具有穩定、已知輸入的簡單系統,可以使用時間驅動(Time-driven:TD)的調度算法,它能夠為數據處理提供很好的預測性。這種調度算法本質上是壹種設計時就確定下來的離線的靜態調度方法。在系統的設計階段,在明確系統中所有的處理情況下,對於各個任務的開始、切換、以及結束時間等就事先做出明確的安排和設計。這種調度算法適合於那些很小的嵌入式系統、自控系統、傳感器等應用環境。
這種調度算法的優點是任務的執行有很好的可預測性,但最大的缺點是缺乏靈活性,並且會出現有任務需要被執行而CPU卻保持空閑的情況。
2. 通用Linux系統中的CPU調度
通用Linux系統支持實時和非實時兩種進程,實時進程相對於普通進程具有絕對的優先級。對應地,實時進程采用SCHED_FIFO或者SCHED_RR調度策略,普通的進程采用SCHED_OTHER調度策略。
在調度算法的實現上,Linux中的每個任務有四個與調度相關的參數,它們是rt_priority、policy、priority(nice)、counter。調度程序根據這四個參數進行進程調度。
在SCHED_OTHER 調度策略中,調度器總是選擇那個priority+counter值最大的進程來調度執行。從邏輯上分析,SCHED_OTHER調度策略存在著調度周期(epoch),在每壹個調度周期中,壹個進程的priority和counter值的大小影響了當前時刻應該調度哪壹個進程來執行,其中 priority是壹個固定不變的值,在進程創建時就已經確定,它代表了該進程的優先級,也代表這該進程在每壹個調度周期中能夠得到的時間片的多少; counter是壹個動態變化的值,它反映了壹個進程在當前的調度周期中還剩下的時間片。在每壹個調度周期的開始,priority的值被賦給 counter,然後每次該進程被調度執行時,counter值都減少。當counter值為零時,該進程用完自己在本調度周期中的時間片,不再參與本調度周期的進程調度。當所有進程的時間片都用完時,壹個調度周期結束,然後周而復始。另外可以看出Linux系統中的調度周期不是靜態的,它是壹個動態變化的量,比如處於可運行狀態的進程的多少和它們priority值都可以影響壹個epoch的長短。值得註意的壹點是,在2.4以上的內核中, priority被nice所取代,但二者作用類似。
可見SCHED_OTHER調度策略本質上是壹種比例***享的調度策略,它的這種設計方法能夠保證進程調度時的公平性--壹個低優先級的進程在每壹個epoch中也會得到自己應得的那些CPU執行時間,另外它也提供了不同進程的優先級區分,具有高priority值的進程能夠獲得更多的執行時間。
對於實時進程來說,它們使用的是基於實時優先級rt_priority的優先級調度策略,但根據不同的調度策略,同壹實時優先級的進程之間的調度方法有所不同:
SCHED_FIFO:不同的進程根據靜態優先級進行排隊,然後在同壹優先級的隊列中,誰先準備好運行就先調度誰,並且正在運行的進程不會被終止直到以下情況發生:1.被有更高優先級的進程所強占CPU;2.自己因為資源請求而阻塞;3.自己主動放棄CPU(調用sched_yield);
SCHED_RR:這種調度策略跟上面的SCHED_FIFO壹模壹樣,除了它給每個進程分配壹個時間片,時間片到了正在執行的進程就放棄執行;時間片的長度可以通過sched_rr_get_interval調用得到;
由於Linux系統本身是壹個面向桌面的系統,所以將它應用於實時應用中時存在如下的壹些問題:
Linux系統中的調度單位為10ms,所以它不能夠提供精確的定時;
當壹個進程調用系統調用進入內核態運行時,它是不可被搶占的;
Linux內核實現中使用了大量的封中斷操作會造成中斷的丟失;
由於使用虛擬內存技術,當發生頁出錯時,需要從硬盤中讀取交換數據,但硬盤讀寫由於存儲位置的隨機性會導致隨機的讀寫時間,這在某些情況下會影響壹些實時任務的截止期限;
雖然Linux進程調度也支持實時優先級,但缺乏有效的實時任務的調度機制和調度算法;它的網絡子系統的協議處理和其它設備的中斷處理都沒有與它對應的進程的調度關聯起來,並且它們自身也沒有明確的調度機制;
3. 各種實時Linux系統
3.1. RT-Linux和RTAI
RT -Linux是新墨西哥科技大學(New Mexico Institute of Technology)的研究成果[RTLinuxWeb][Barabanov97]。它的基本思想是,為了在Linux系統中提供對於硬實時的支持,它實現了壹個微內核的小的實時操作系統(我們也稱之為RT-Linux的實時子系統),而將普通Linux系統作為壹個該操作系統中的壹個低優先級的任務來運行。另外普通Linux系統中的任務可以通過FIFO和實時任務進行通信。RT-Linux的框架如圖 1所示:
圖 1 RT-Linux結構
RT -Linux的關鍵技術是通過軟件來模擬硬件的中斷控制器。當Linux系統要封鎖CPU的中斷時時,RT-Linux中的實時子系統會截取到這個請求,把它記錄下來,而實際上並不真正封鎖硬件中斷,這樣就避免了由於封中斷所造成的系統在壹段時間沒有響應的情況,從而提高了實時性。當有硬件中斷到來時, RT-Linux截取該中斷,並判斷是否有實時子系統中的中斷例程來處理還是傳遞給普通的Linux內核進行處理。另外,普通Linux系統中的最小定時精度由系統中的實時時鐘的頻率決定,壹般Linux系統將該時鐘設置為每秒來100個時鐘中斷,所以Linux系統中壹般的定時精度為 10ms,即時鐘周期是10ms,而RT-Linux通過將系統的實時時鐘設置為單次觸發狀態,可以提供十幾個微秒級的調度粒度。
RT-Linux實時子系統中的任務調度可以采用RM、EDF等優先級驅動的算法,也可以采用其他調度算法。
RT -Linux對於那些在重負荷下工作的專有系統來說,確實是壹個不錯的選擇,但他僅僅提供了對於CPU資源的調度;並且實時系統和普通Linux系統關系不是十分密切,這樣的話,開發人員不能充分利用Linux系統中已經實現的功能,如協議棧等。所以RT-Linux適合與工業控制等實時任務功能簡單,並且有硬實時要求的環境中,但如果要應用與多媒體處理中還需要做大量的工作。
意大利的RTAI( Real-Time Application Interface )源於RT-Linux,它在設計思想上和RT-Linux完全相同。它當初設計目的是為了解決RT-Linux難於在不同Linux版本之間難於移植的問題,為此,RTAI在 Linux 上定義了壹個實時硬件抽象層,實時任務通過這個抽象層提供的接口和Linux系統進行交互,這樣在給Linux內核中增加實時支持時可以盡可能少地修改 Linux的內核源代碼。
3.2. Kurt-Linux
Kurt -Linux由Kansas大學開發,它可以提供微秒級的實時精度[KurtWeb] [Srinivasan]。不同於RT-Linux單獨實現壹個實時內核的做法,Kurt -Linux是在通用Linux系統的基礎上實現的,它也是第壹個可以使用普通Linux系統調用的基於Linux的實時系統。
Kurt-Linux將系統分為三種狀態:正常態、實時態和混合態,在正常態時它采用普通的Linux的調度策略,在實時態只運行實時任務,在混合態實時和非實時任務都可以執行;實時態可以用於對於實時性要求比較嚴格的情況。
為了提高Linux系統的實時特性,必須提高系統所支持的時鐘精度。但如果僅僅簡單地提高時鐘頻率,會引起調度負載的增加,從而嚴重降低系統的性能。為了解決這個矛盾, Kurt-Linux采用UTIME所使用的提高Linux系統中的時鐘精度的方法[UTIMEWeb]:它將時鐘芯片設置為單次觸發狀態(One shot mode),即每次給時鐘芯片設置壹個超時時間,然後到該超時事件發生時在時鐘中斷處理程序中再次根據需要給時鐘芯片設置壹個超時時間。它的基本思想是壹個精確的定時意味著我們需要時鐘中斷在我們需要的壹個比較精確的時間發生,但並非壹定需要系統時鐘頻率達到此精度。它利用CPU的時鐘計數器TSC (Time Stamp Counter)來提供精度可達CPU主頻的時間精度。
對於實時任務的調度,Kurt-Linux采用基於時間(TD)的靜態的實時CPU調度算法。實時任務在設計階段就需要明確地說明它們實時事件要發生的時間。這種調度算法對於那些循環執行的任務能夠取得較好的調度效果。
Kurt -Linux相對於RT-Linux的壹個優點就是可以使用Linux系統自身的系統調用,它本來被設計用於提供對硬實時的支持,但由於它在實現上只是簡單的將Linux調度器用壹個簡單的時間驅動的調度器所取代,所以它的實時進程的調度很容易受到其它非實時任務的影響,從而在有的情況下會發生實時任務的截止期限不能滿足的情況,所以也被稱作嚴格實時系統(Firm Real-time)。目前基於Kurt-Linux的應用有:ARTS(ATM Reference Traffic System)、多媒體播放軟件等。另外Kurt-Linux所采用的這種方法需要頻繁地對時鐘芯片進行編程設置。
3.3. RED-Linux
RED -Linux是加州大學Irvine分校開發的實時Linux系統[REDWeb][ Wang99],它將對實時調度的支持和Linux很好地實現在同壹個操作系統內核中。它同時支持三種類型的調度算法,即:Time-Driven、 Priority-Dirven、Share-Driven。
為了提高系統的調度粒度,RED-Linux從RT-Linux那兒借鑒了軟件模擬中斷管理器的機制,並且提高了時鐘中斷頻率。當有硬件中斷到來時,RED-Linux的中斷模擬程序僅僅是簡單地將到來的中斷放到壹個隊列中進行排隊,並不執行真正的中斷處理程序。
另外為了解決Linux進程在內核態不能被搶占的問題, RED-Linux在Linux內核的很多函數中插入了搶占點原語,使得進程在內核態時,也可以在壹定程度上被搶占。通過這種方法提高了內核的實時特性。
RED-Linux的設計目標就是提供壹個可以支持各種調度算法的通用的調度框架,該系統給每個任務增加了如下幾項屬性,並將它們作為進程調度的依據:
Priority:作業的優先級;
Start-Time:作業的開始時間;
Finish-Time:作業的結束時間;
Budget:作業在運行期間所要使用的資源的多少;
通過調整這些屬性的取值及調度程序按照什麽樣的優先順序來使用這些屬性值,幾乎可以實現所有的調度算法。這樣的話,可以將三種不同的調度算法無縫、統壹地結合到了壹起。