第2章 嵌入式操作系統
嵌入式操作系統是嵌入式軟件的重要組成部分,在嵌入式操作系統的支持下開發嵌入式軟件,不僅極大地減少了開發的工作量,而且提高了嵌入式應用軟件的可移植性。本章首先介紹嵌入式操作系統的基本概念;然后討論嵌入式操作系統的基本功能和多內核嵌入式操作系統原理;最后介紹幾種比較有代表性的嵌入式操作系統。
2.1 嵌入式操作系統概述
嵌入式操作系統是一種用于支持嵌入式應用程序的操作系統。它是一個介于應用程序和嵌入式計算機系統硬件之間的程序集合,其任務是控制和管理嵌入式系統中的硬件和軟件資源,以方便嵌入式系統的使用者。
2.1.1 為什么要使用嵌入式操作系統
并不是所有的嵌入式系統上面都需要有一個嵌入式操作系統。一些本身功能很簡單的嵌入式系統(如一個普通的空調控制器)出于效率和成本考慮,通常不使用嵌入式操作系統。但當一個嵌入式系統軟件的復雜程度達到一定的水平,其硬件又具備充足的處理能力時,使用嵌入式操作系統就是理所當然的選擇。一般說來,當一個嵌入式系統有以下需求時就要使用嵌入式操作系統。
1. 系統需要運行多個任務
一些功能簡單的嵌入式系統只需要運行幾個固定的任務,可以由應用任務自己來管理硬件,完成相互之間的協調工作。但是當嵌入式系統需要運行很多任務,并且任務之間的關系很復雜時,還由應用任務自己來負責管理和協調工作,就會給應用程序的開發者帶來很大麻煩,軟件出現錯誤的概率也會顯著增加。如果把管理方面的工作統統交給操作系統來完成,就可以避免出現這些問題。
2. 系統需要直觀的用戶界面
一些嵌入式系統并不是在啟動之后就默默地去運行,它們需要同用戶進行交互,最好能通過窗口式的圖形用戶界面進行這種交互。這就要用到窗口系統,而窗口系統離不開操作系統的支持。
3. 系統需要有網絡功能
在沒有操作系統的情況下,支持網絡功能并不是不可能的事情。比如,TCP/IP協議就可以用硬件芯片來實現。但使用這樣的芯片會增加成本,并且網絡協議會不斷升級,用硬件芯片則無法同步升級。而在有操作系統的嵌入式計算機系統中,可以根據需要定制網絡協議,以適應各種網絡環境的需求,也便于跟上網絡協議更新的步伐。
4. 系統需要用到數據庫管理系統
一些移動信息設備需要使用移動數據庫管理系統解決移動計算環境下的數據管理問題。比如,掌上計算機、PDA、車載設備、智能手機等就經常有此方面的需求。還有一些應用問題需要利用嵌入式實時數據庫管理系統進行實時數據的采集和處理。無論是移動數據庫管理系統還是嵌入式實時數據庫管理系統都離不開操作系統的支持。
5. 系統需要不斷進行二次開發
如果要經常進行二次開發工作,使用嵌入式操作系統是一個明智的選擇。嵌入式操作系統提供一系列供開發人員使用的API接口。在這些接口之上進行開發,可以免去很多繁瑣的底層開發工作,這不僅提高了嵌入式系統的開發效率,而且也提高了嵌入式應用軟件的可移植性。
2.1.2 嵌入式操作系統與實時操作系統
在定義什么是實時操作系統之前,需要先明確什么是實時系統。簡單地講,一個實時系統是能滿足以下要求的系統:當外部事件到來時,計算機能立即進行處理,使得在指定的時間內能完成對事件的處理。而且外部事件到來的時間完全是隨機的,沒有周期性規律。
因此一個實時系統要正確運行,除了能產生正確的處理結果之外,還必須在預定的時間之內完成處理工作。我們稱前一個要求為功能的正確性,后一個要求為時間的正確性。對一個實時系統來說,這兩種正確性是同等重要的。
根據對系統的響應時間是否有嚴格的要求,可將實時系統分為硬實時系統和軟實時系統兩類。硬實時系統對響應時間有一個剛性的、不可改變的限制,它不允許出現任何超出時限的錯誤。超時錯誤會導致系統失敗,或系統不能實現預期目標。軟實時系統對響應時間的要求是柔性的,它可以容忍偶然的超時錯誤出現。超時錯誤造成的后果并不嚴重,僅僅是降低了系統的吞吐量。
介紹了實時系統的概念后,我們再回過頭來看一看什么是實時操作系統。實時操作系統可以這樣來定義:實時操作系統是具有實時性,能支持實時系統工作的操作系統。它必須能保證實時任務在預定的時間內完成,其首要任務是調度一切可以利用的資源完成實時任務,其次才著眼于提高整個計算機系統的使用效率。
由于早期的嵌入式系統幾乎都用于控制目的,因此或多或少地都有些實時要求。所以那時“嵌入式操作系統”實際上就是“實時操作系統(RTOS)”的代名詞。近幾年來,由于掌上計算機設備的出現,產生了一些沒有實時要求的嵌入式系統。此時,“嵌入式操作系統”和“實時操作系統”就成了不同的概念。

圖2.1 嵌入式操作系統和實時操作系統之間的關系
嵌入式操作系統和實時操作系統之間的關系如圖2.1所示。從圖中可以看到,大部分嵌入式操作系統都是實時操作系統。大部分實時操作系統也都是嵌入式操作系統。它們二者間有很大的交集,但確有不適合用在嵌入式系統上使用的實時操作系統和不支持實時應用的嵌入式操作系統。我們稱屬于交集部分的操作系統為實時嵌入式操作系統。
實時嵌入式操作系統分配和使用CPU時間等系統資源的策略和通用操作系統有很多不同之處。這主要體現在以下三個方面。
① 對于通用操作系統來說,保障總體的效率是主要的目標,必要時寧可犧牲個別任務的響應速度來達到提高總體效率的目的。而實時嵌入式操作系統卻正好相反,必要時寧可犧牲總體效率也要保證個別任務的響應速度。
② 對于通用操作系統來說,公正性更為重要,在需要的時候會從占有資源較多的任務那里拿走一些給占有資源較少的任務。而對于實時嵌入式操作系統來說,高優先級任務的運行更為重要,必要時寧可從本來占有資源就比較少的任務那里拿走一些資源,也要保證高優先級任務的需要。相應地,通用操作系統性能的分析是統計分析、平均值分析,而實時嵌入式操作系統性能的分析則是“最壞情況”分析。
③ 通用操作系統要充分利用CPU的處理能力。而實時嵌入式操作系統需要有意讓CPU的處理能力供過于求,使CPU運行于輕負荷狀態,以確保系統的響應速度。
2.1.3 嵌入式操作系統的主要性能指標
嵌入式操作系統的性能指標是評價嵌入式操作系統的客觀依據。可以分為時間性能指標和存儲開銷指標兩類。
1. 嵌入式操作系統的時間性能指標
嵌入式操作系統主要有中斷延遲時間、最大關中斷時間、中斷響應時間、中斷恢復時間、中斷處理時間、任務上下文切換時間、任務響應時間、系統調用執行時間等一些時間性能指標。這些時間性能指標或多或少地都要受到硬件因素的影響,如CPU速度、存儲器速度、存儲空間大小、高速緩存(Cache)大小等,在評價嵌入式操作系統的時間性能時,必須要考慮這些因素。
嵌入式操作系統的時間性能指標與中斷有密切的關系。為此先討論嵌入式操作系統處理中斷的過程。
中斷指在計算機執行期間,由于CPU外部某種預期或非預期事件的發生,導致程序的正常執行流程發生改變的過程。引起中斷發生的事件稱為中斷請求。中斷請求一旦得到響應,CPU將先保存當前被中斷的任務的部分上下文,然后轉到相應的中斷服務程序中去執行。執行完中斷服務程序后,根據嵌入式操作系統采用的調度策略,將會采取不同的后續處理步驟。下面討論兩種典型的中斷處理過程:一種是非搶占式調度的操作系統處理中斷的過程,另一種是搶占式調度的操作系統處理中斷的過程。
如圖2.2所示,嵌入式操作系統一般允許中斷嵌套。中斷嵌套是指如果在處理一個中斷請求(中斷請求A)期間有另外一個更重要的中斷請求(中斷請求B)發生,操作系統將暫停對當前中斷請求(中斷請求A)的處理,轉去處理這個更重要的中斷請求(中斷請求B)。在下面的討論中,為避免問題表達過于繁瑣,假設在處理中斷請求的過程中沒有發生中斷嵌套。
非搶占式調度的操作系統的處理中斷過程如圖2.3所示。可以看出,在非搶占式調度的操作系統中,中斷服務程序運行完后,一定是繼續運行被中斷了的任務。這個過程的步驟如下。

圖2.2 發生中斷嵌套的情況

圖2.3 非搶占式調度的操作系統處理中斷的過程
① 發生中斷請求:中斷來到,但還不能被CPU響應,這也許是因為CPU還沒執行完當前的指令,也許是因為中斷已被操作系統或用戶程序關閉。
② 響應中斷:CPU執行完當前指令并且中斷打開,使中斷被響應。
③ 保存關鍵寄存器,獲取中斷向量,轉到中斷服務程序:這些工作全部由硬件完成。下文中“硬件開始處理中斷請求到開始執行中斷服務程序第一條指令之間的時間”指的就是完成這些工作所花費的時間。
④ 保存任務上下文:中斷服務程序保存任務上下文,主要是各寄存器的內容。
⑤ 執行中斷服務程序入口函數:中斷服務程序調用操作系統的中斷服務程序入口函數,通知操作系統系統已進入中斷處理中,該入口函數會把中斷嵌套層數計數器的值加1,記錄下當前的中斷嵌套層數。
⑥ 執行用戶中斷服務程序:此時實際開始對中斷請求進行處理。用戶中斷服務程序所做的工作完全取決于實際的需要,操作系統不會加以限制。但要注意,在用戶中斷服務中做的事要盡可能地少,而把大部分的工作留給協同工作的任務去完成。用戶中斷服務程序通知某任務去做事情的方法是調用操作系統提供的任務同步或任務通信系統調用,這可能導致接收通知的任務轉換到就緒狀態。
⑦ 執行中斷服務程序出口函數:用戶的中斷服務代碼運行完后,調用操作系統的中斷服務程序出口函數,通知操作系統系統退出此次中斷處理,中斷服務程序出口函數會把中斷嵌套層數計數器的值減1。當嵌套層數計數器減為0時,所有中斷都已經處理完。
⑧ 恢復任務上下文:恢復在進入中斷處理時保存的寄存器值。
⑨ 中斷返回:執行中斷返回指令。
搶占式調度的操作系統處理中斷的過程如圖2.4所示。可以看出,在搶占式調度的操作系統中,用戶中斷服務程序執行完之后,將調用操作系統的中斷服務程序出口函數,通知操作系統系統退出此次中斷處理,中斷服務程序出口函數會把中斷嵌套層數計數器的值減1。當嵌套層數計數器的值為0時,表示所有中斷都已處理完畢。此時系統如果沒有禁止調度,操作系統的中斷服務程序出口函數將執行調度程序。調度程序在執行的過程中需要判斷是否應當進行任務切換。如果原先被中斷的任務在所有處于就緒狀態的任務中仍然是優先級最高的任務,那么不需要進行任務切換,系統將返回到被中斷的任務繼續執行,如果原先被中斷的任務在所有處于就緒狀態的任務中已經不是優先級最高的任務,那么就需要進行任務切換,系統將執行另外一個任務。這樣在中斷返回時將出現A和B兩種不同的情況。一種A是繼續運行原先被中斷的任務,另一種B是運行新被調度程序選中的任務。出現情況B的原因有多種,可能是中斷服務程序或其他任何一個嵌套的中斷服務程序使另一個優先級更高的任務進入了就緒態,也可能是原先被中斷任務的狀態已經被中斷服務程序改變,如已經進入阻塞狀態。在出現情況B時由于要進行任務切換,操作系統中斷服務程序出口函數的執行時間要長一些。

圖2.4 搶占式調度的操作系統處理中斷的過程
中斷處理過程的第①步至第⑥步對A和B兩種情況是相同的,并且每一步所做的工作與非搶占式調度的操作系統完全相同。第、
、
步對應于情況A,即中斷處理結束后繼續運行原先被中斷的任務的情況。第
、
、
步對應于情況B,即中斷處理結束后運行新被調度程序選中的任務的情況。
(1)中斷延遲時間
如圖2.4所示,中斷延遲時間指從中斷請求發生到CPU響應該中斷請求,并且開始執行中斷服務程序所經歷的延遲時間。中斷延遲時間受到以下3種時間因素的影響:
① 處理高優先級中斷的時間;
② 硬件開始處理中斷請求到開始執行中斷服務程序第一條指令之間的時間;
③ 最大關中斷時間。
因為高優先級中斷會屏蔽低優先級的中斷,所以一個中斷請求必須等優先級比它高的中斷請求被處理完之后才能得到處理。又因為中斷是可以嵌套的,所以“處理高優先級中斷的時間”與中斷嵌套的層數及每層中斷的處理難度都有密切的關系。而中斷嵌套的層數及每層中斷的處理難度又與應用問題有直接的關系,對于不同的應用問題中斷嵌套的層數可能不同,每層中斷的中斷服務程序的執行時間也不相同。總之嵌入式操作系統的設計者無法對“處理高優先級中斷的時間”進行優化。
“硬件開始處理中斷請求到開始執行中斷服務程序第一條指令之間的時間”完全由硬件決定,嵌入式操作系統的設計者也無法對這一時間進行優化。在這段時間內要進行保存關鍵寄存器的內容、獲取中斷向量、并根據中斷向量給出的地址轉到中斷服務程序等一系列的工作。
中斷延遲時間與系統關中斷時間有直接關系。操作系統在進入臨界區代碼之前要關中斷,執行完臨界區代碼之后再打開中斷。關中斷的時間越長,中斷延遲就越長,在嚴重情況下還可能引起中斷請求丟失。對實時系統來說總是關心最極端情況下的處理結果,因此在確定中斷延遲時間時,應當測量的是最大關中斷時間,而不是平均關中斷時間,更不是最小關中斷時間。最大關中斷時間是嵌入式操作系統的設計者必須加以優化的一個時間性能指標。
(2)最大關中斷時間
最大關中斷時間的長短取決于操作系統關中斷的時間和應用程序關中斷的時間兩個因素。為了縮短最大關中斷時間,在設計和編寫操作系統和應用程序時應當盡可能地減少關中斷的時間。在設計操作系統時,如果為了保證臨界區代碼的安全,采用一進入系統內核就關閉中斷的方法來進行互斥,那么操作系統的設計雖然很簡單,系統的安全也能夠得到保障,但關中斷的時間就會很長。其實通過仔細分析操作系統內核的代碼,就可以發現其中存在一些非臨界區。在這些非臨界區中開中斷,增加操作系統內核中的可搶占點,可以顯著縮短關中斷的時間。
(3)中斷響應時間
如圖2.4所示,中斷響應時間指從發生中斷請求到開始執行用戶中斷服務程序的第一條指令之間的時間。應注意中斷延遲時間與中斷響應時間的區別。中斷延遲時間指從發生中斷請求到開始執行中斷服務程序的第一條指令之間的時間。中斷響應時間和中斷延遲時間之間的關系可以用下面的算式表示:
中斷響應時間=中斷延遲時間+保存任務上下文的時間+執行中斷服務程序入口函數的時間
由于中斷延遲時間受到處理高優先級中斷的時間、硬件開始處理中斷請求到開始執行中斷服務程序第一條指令之間的時間、最大關中斷時間的影響,所以中斷響應時間將受到以下5種時間因素的影響:
① 處理高優先級中斷的時間;
② 硬件開始處理中斷請求到開始執行中斷服務程序第一條指令之間的時間;
③ 最大關中斷時間;
④ 保存任務上下文的時間;
⑤ 執行中斷服務程序入口函數的時間。
任務上下文指CPU寄存器中的內容。保存任務上下文的時間主要取決于處理器的速度和任務上下文的數量。處理器的速度高,任務上下文少,保存任務上下文所花費的時間就短,反之保存任務上下文所花費的時間就長。
執行中斷服務程序入口函數時所做的工作主要是把中斷嵌套層數計數器的值加1,記錄下當前的中斷嵌套層數。某些嵌入式操作系統也會在中斷服務程序入口函數中做一些其他的工作。但總的來說,執行中斷服務程序入口函數所花費的時間是一個確定值。
(4)中斷恢復時間
如圖2.4所示,中斷恢復時間是從用戶中斷服務程序執行完畢到繼續執行原先被中斷的任務或開始執行新被調度程序選中的任務之間的時間。中斷恢復時間受到以下3種時間因素的影響:
① 執行中斷服務程序出口函數的時間;
② 恢復任務上下文的時間;
③ 執行中斷返回指令的時間。
在需要進行任務切換時,中斷服務程序出口函數的執行時間會比不進行任務切換時有所延長,但總的來說,執行中斷服務程序出口函數的時間是一個確定值。和保存任務上下文的時間一樣,恢復任務上下文的時間主要取決于處理器的速度和任務上下文的數量。執行中斷返回指令的時間完全取決于處理器的性能,但不論怎樣,這一時間是很短的。
(5)中斷處理時間
中斷處理時間即執行用戶中斷服務程序所花費的時間。這一時間的長短與用戶中斷服務程序所要完成的工作量有關。中斷服務程序所要完成的工作量取決于具體的情況,無法加以限制。所以中斷處理時間這一指標與嵌入式操作系統的其他時間性能指標有一定的區別。
中斷服務程序所要完成的工作量雖然不能隨意減少,但縮短中斷處理時間對于實時嵌入式操作系統卻是非常有意義的。因為無論是否打開中斷,中斷服務程序的運行過程都不能被優先級較低的中斷請求所中斷,這會導致某些低優先級中斷的中斷延遲時間延長,降低了系統的實時性能。
在中斷處理的工作量是一個恒定值的前提下,縮短中斷處理時間的方法是,將工作在中斷服務程序和中斷服務任務之間進行合理分配。一般情況下,處理中斷時所要做的工作包括確定產生中斷請求的設備、從產生中斷請求的設備處取得數據、根據得到的數據進行中斷處理等。確定產生中斷請求的設備、從產生中斷請求的設備處取得數據一般是由中斷服務程序來完成,但進行中斷處理則既可以由中斷服務程序來完成也可以由中斷服務任務來完成。如果將全部或部分進行中斷處理的工作交給中斷服務任務來完成,那么中斷處理時間顯然就可以縮短。
將進行中斷處理的工作交給中斷服務任務來完成雖然可以縮短中斷處理時間,但并不總能達到提高系統性能的目的,有時還得不償失。原因如下,在將進行中斷處理的工作交給中斷服務任務來完成時,中斷服務程序所做的工作變成了以下幾項:確定產生中斷請求的設備、從產生中斷請求的設備取得數據、通知實際進行中斷處理的中斷服務任務。通知實際進行中斷處理的中斷服務任務可以采用信號、信號量、消息、事件等同步機制。這種通知工作需要一定的時間。如果處理中斷需要花費的時間很短,這樣做就很不值得。而且將進行中斷處理的工作交給中斷服務任務后,實際開始中斷處理的時間要延遲到中斷服務任務被調度程序選中之后。所以,即使中斷服務任務的優先級非常高,也會有一定的調度延遲。但是在直接由中斷服務程序進行中斷處理的情況下,這個調度延遲是不存在的。這就是為什么在將進行中斷處理的工作交給中斷服務任務來完成時,并不總是能提高系統性能的原因。
(6)任務上下文切換時間
在多任務操作系統中,任務上下文切換指CPU的控制權由當前運行的任務轉移到另外一個就緒任務的過程。發生任務上下文切換之后,當前運行的任務將變為就緒或者阻塞態,另一個被調度程序選中的就緒任務將投入運行。由于在操作系統運行的過程中任務上下文切換會經常發生,因此任務上下文切換時間的長短將直接影響到整個系統的性能。
如圖2.5所示,任務上下文切換的過程分為3個階段:保存退出運行的任務的上下文、選擇將投入運行的任務、恢復將投入運行的任務的上下文。任務上下文切換時間就是這3個階段所花費的時間的總和。

圖2.5 任務上下文切換的過程
在這3個階段所花費的時間中,保存退出運行的任務的上下文所花費的時間與恢復將投入運行的任務的上下文所花費的時間主要取決于處理器的速度和任務上下文的數量。選擇將投入運行的任務所花費的時間則主要取決于操作系統的調度程序所采用的任務選擇算法。
任務上下文指CPU寄存器中的內容。這些內容保存在任務的當前狀態保存區中,如任務的堆棧或任務控制塊之中。當一個任務被投入運行時這些內容將被裝入到CPU寄存器中,一個任務退出運行時,CPU中各個寄存器的值將會保存到任務的當前狀態保存區中。因此,CPU內部的寄存器越多,保存和恢復上下文的工作就越重。所以任務上下文切換時間與CPU有多少寄存器有直接的關系。
當嵌入式計算機帶有浮點協處理器時,在進行任務上下文切換時通常也要對浮點協處理器中的寄存器內容進行保存和恢復,這更加耗費時間。由于并不是所有的任務都要使用浮點協處理器,所以操作系統可以采取某些優化策略,并不需要每次進行任務切換時都保存和恢復浮點協處理器中的寄存器內容。
選擇將投入運行的任務所花費的時間雖然也受到處理器速度的影響,但更主要的取決于操作系統的調度程序所采用的任務選擇算法。一些選擇任務算法與系統中處于就緒狀態的任務數有關。任務數少,選擇任務花費的時間就短,任務數多,選擇任務花費的時間就長。這對于有很強實時性要求操作系統是不能接受的。強實時的嵌入式操作系統要求選擇任務所花費的時間是確定的,不能隨系統中的就緒任務數發生變化。這種操作系統必須采用一種與就緒任務數無關的任務選擇算法。有些任務選擇算法是可以滿足這個要求的。如基于優先級位圖的任務選擇算法就能夠保證任務選擇過程所花費的時間具有確定性。
(7)任務響應時間
如圖2.4所示,任務響應時間指從一個任務對應的中斷發生到該任務開始運行之間所經歷的時間。任務響應時間又稱調度延遲。如果一個任務在等待某一中斷請求將其喚醒,那么這個中斷請求發生后,其中斷服務程序將使該任務進入就緒狀態。如果這一任務有足夠高的優先級,那么在當前運行的任務停止運行后(停止運行的原因是多樣的,可能是因為被搶占,可能是因等待某種資源而被阻塞,也可能是因為運行時間片到期),這個新進入就緒狀態的任務就將被投入運行。任務響應時間就是指這一過程所花費的時間。
任務響應時間受到以下因素的影響:
① 操作系統的調度算法;
② 系統禁止調度的時間;
③ 中斷延遲時間;
④ 任務上下文切換時間;
⑤ 中斷處理時間。
操作系統的調度算法是決定任務響應時間的主要因素之一。采用搶占式最高優先級優先調度算法的操作系統任務響應時間明顯較短。因為這種操作系統是即時搶占的,一旦任務的狀態發生了變化,操作系統馬上就會進行調度,使高優先級的任務投入運行,如圖2.4所示,這時任務響應時間很好計算,它的值等于中斷延遲時間、執行用戶中斷服務程序的時間、中斷恢復時間三者之和。有些操作系統并不是在任務狀態發生變化后馬上就能進行調度,而是要等待到某一個特定的時刻(如當前運行的任務因等待某種資源被阻塞時),所以其任務響應時間就比較長。
系統禁止調度的時間也是影響任務響應時間的主要因素之一。在操作系統禁止調度時,即使中斷服務程序使一個優先級更高的任務進入就緒狀態,中斷處理結束后也無法切換到這個高優先級任務運行,任務響應時間將變得很長。禁止調度是一種互斥方法。一個實時性能良好的操作系統不會使用這種方法進行互斥,但操作系統經常會提供一個可以禁止/允許調度的系統調用。在應用程序中雖然可以使用這個系統調用,但使用的時候一定要慎重,以免使任務響應時間變得過長。
另外,從前面的介紹中可以看出:中斷延遲時間、任務上下文切換時間、中斷處理時間等因素也都會對任務響應時間發生影響。
(8)系統調用執行時間
系統調用執行時間也是評價一個嵌入式操作系統性能優劣的指標。然而,由于調用參數和系統運行情況的差別,同一個系統調用的每次執行,可能會經歷不同的路徑,所以其執行時間不是一個定值,而是會在一定區間之內波動。
實時嵌入式操作系統,關心的是系統調用的最大執行時間;非實時嵌入式操作系統,關心的是系統調用的平均執行時間。所以在評價系統調用執行時間時,應該根據可能的使用情況設計不同的測試用例,獲取其最大值和平均值。另外,一個操作系統中的各種系統調用的使用頻率是不同的,一些系統調用經常使用,另一些系統調用很少使用。所以在對一個嵌入式操作系統的系統調用執行時間進行整體評價時應對不同的系統調用賦予不同的權重。
2. 嵌入式操作系統的存儲開銷指標
由于成本、功耗和便攜性要求等原因,嵌入式系統的存儲資源一般都比較有限,因此嵌入式操作系統的存儲開銷也是它的重要性能指標。在這一點上嵌入式操作系統與通用操作系統有明顯的區別。嵌入式操作系統主要有代碼存儲開銷和數據存儲開銷兩種存儲開銷指標。
(1)代碼存儲開銷
代碼存儲開銷指存儲嵌入式操作系統(內核)本身所需要的內存數量。嵌入式操作系統代碼的大小取決于多種因素,其值一般與操作系統的功能有直接關系,分布在從幾千字節到幾百字節的區間內。例如,用于無線傳感器的嵌入式操作系統代碼必須限制在幾字節的水平,而用于數字電視和機頂盒的嵌入式操作系統代碼達到幾百字節也是完全可以接受的。
(2)數據存儲開銷
嵌入式操作系統在運行過程中需要一定數量的存儲空間來存放工作數據。數據存儲開銷指存儲這些工作數據所需要的內存數量。這些內存按用途分為以下三類:
① 操作系統變量所占的內存。這一部分內存的大小固定,不會隨著操作系統的運行發生變化。
② 操作系統對象及其控制結構所占的內存。操作系統對象指任務、信號量、事件、信號、消息、軟件定時器、堆等。這些對象的數目有可能會隨著系統的運行發生變化。例如,在操作系統支持的任務數不固定的情況下,任務控制塊的數量可以隨著系統中任務數的多少發生變化。
③ 堆棧所占的內存。操作系統使用的堆棧主要有任務堆棧和中斷堆棧兩種。在多任務操作系統中,操作系統給每個任務提供一個單獨的堆棧空間。函數調用的返回地址、函數的局部變量等都保存在任務堆棧中。任務堆棧的尺寸一般由應用程序開發者指定,但準確估計出一個接近實際需要的值是相當困難的。為了防止任務堆棧溢出往往要指定一個較大的值。在允許中斷嵌套時,任務上下文(各種寄存器的值)、中斷服務程序的局部變量也可以保存在任務堆棧中,但為了避免在中斷嵌套層數過多時任務堆棧發生溢出,一些操作系統采用了一個中斷堆棧專門來保存中斷嵌套時產生的任務上下文和中斷服務程序的局部變量,而不是將這些信息保存在任務堆棧中。這種做法降低了由于任務堆棧空間的實際需求難以確定所帶來的問題,提高了系統的可靠性。
2.1.4 嵌入式操作系統的結構
嵌入式操作系統的結構可分為單塊結構、層次結構和微內核結構三類。單塊結構的嵌入式操作系統和層次結構的嵌入式操作系統又統稱為一體化結構的嵌入式操作系統。
1. 單塊結構的嵌入式操作系統
如圖2.6所示,單塊結構的嵌入式操作系統由許多模塊組成,這些模塊通常在核心態下運行。模塊之間沒有層次關系,可以根據需要隨意地相互調用。在系統規模較小時,這種結構顯得比較靈活。但總的來說,單塊結構操作系統很難調試和維護。如果一個模塊被改變,對其他的模塊可能會有很大的影響,導致其他模塊中出現一些錯誤。操作系統中包含的模塊越多,模塊間的調用關系越復雜,整個系統就越混亂。
2. 層次結構的嵌入式操作系統
如圖2.7所示,層次結構的嵌入式操作系統按層次關系進行組織。整個系統由多個層次所組成,并且只允許上層調用下層,而下層不能反過來調用上層,操作系統的結構清晰,提高了系統的安全性。在一個理想的層次結構系統中,各層之間不能越層調用。比如第n層不能越過第n-1層直接調用第n-2層。在這種嚴格意義的層次系統中,很容易在不影響其他層的情況下替換其中的某一層。但在一個具體的操作系統中,出于性能方面的考慮,各層之間不會嚴格地遵守逐層調用的規則。而是允許上層越過直接下層調用更底層的功能。例如,應用程序發出的系統調用就可以直接到達對應的功能層。

圖2.6 單塊結構的嵌入式操作系統

圖2.7 層次結構的嵌入式操作系統
3. 微內核結構的嵌入式操作系統
如圖2.8所示,微內核結構的嵌入式操作系統只有一個很小的內核,其中只包含一些必須由內核實現的功能。而把許多不是必須由內核實現的功能都放在了內核之外,運行于用戶態。微內核結構提高了操作系統的模塊化程度,使其結構更清晰,更加易于調試、擴充和剪裁,也很容易實現在不同硬件平臺之間的移植。

圖2.8 微內核結構的嵌入式操作系統
在單塊結構和層次結構兩類操作系統中,操作系統的功能大部分都是由系統內核提供的。系統內核中包含的功能很多,整個操作系統幾乎是一個整體,沒有再劃分內核部分和核外部分。因此把這兩類操作系統統稱為一體化結構的操作系統。這樣按照操作系統內核中包括的功能的多少,操作系統就被分為了微內核結構的操作系統和一體化結構的操作系統兩大類。
大部分嵌入式操作系統都是采用微內核結構,采用一體化結構的嵌入式操作系統相對很少。專門為嵌入式系統開發的操作系統幾乎無一例外地采用了微內核結構,只有某些從通用操作系統演化來的系統采用了一體化結構。
嵌入式操作系統通常采用微內核結構的原因主要來自以下三個方面。
① 使用特征方面的原因:通用計算機面對的是開放的用戶群,一些用戶不需要的功能另一些用戶可能需要。一個功能放在內核中,總會有用處。而且,內核的復雜與否也不是用戶所關心的問題。然而,嵌入式系統的情況則不同。嵌入式系統的用戶群及用戶對功能的要求是相對封閉的。對于特定的嵌入式系統,需要哪些功能、不需要哪些功能基本上是固定的。對于一個具體的嵌入式系統而言,操作系統中的某些多余功能會永遠沒有用途。
② 內存資源方面的原因:相對于通用計算機而言,內存在嵌入式系統中是很有限的資源。以下幾個問題都是限制嵌入式系統中內存數量的原因:第一,價格因素,對多數嵌入式系統而言,內存價格在整個系統的價格中都占一定的比例。第二,供電因素,嵌入式系統經常由電池供電,因此電源供應是一個重要問題,非常需要采用包括減小內存容量在內的各項措施節約系統的耗電。第三,散熱因素,在系統電源有保障的情況下,散熱也是一個問題。嵌入式系統往往要在條件很不利的情況下使用,而且還可能無法采用排風扇一類的散熱措施。例如,很難給一臺PDA安上一個散熱風扇。因此有必要通過減少內存數量來降低系統的散熱。所以,操作系統內核所占的內存數量對于嵌入式系統是個很敏感的問題,減少操作系統內核所占用的內存數量有重要意義。
③ 商業方面的原因:如果嵌入式操作系統的功能大而全,會導致價格較高,顯然既不符合用戶的利益也不符合供應商的利益。在銷售嵌入式操作系統時應當能夠根據用戶的需要按模塊進行銷售。嵌入式操作系統采用微內核結構比采用一體化結構更易于按模塊進行拆分和組合。
既然微內核結構的操作系統比一體化結構的操作系統更適合于嵌入式系統,那么哪些成分必須留在嵌入式操作系統的內核中呢?最小的內核又必須包含哪些成分呢?現在就來討論這些問題。
① 進行任務管理與調度所需的功能必須位于內核中。包括任務調度、任務建立、任務刪除、任務掛起、任務喚醒、任務屬性設置、任務屬性查詢等功能。
② 內存管理功能必須留在在內核中。如頁表的建立和管理必須由內核來實現。
③ 任務通信功能必須由內核來實現。這些功能包括互斥、同步和數據交換機制。內核中沒有這些功能就無法實現任務與任務之間,以及內核與任務之間的通信。
④中斷管理必須由內核來實現。嵌入式系統的CPU響應中斷后會自動切換到核心態,執行中斷服務程序,所以最基本的中斷管理工作只能由內核來實現。
綜上所述,最小的微內核中可以只包括任務管理、內存管理、任務通信和中斷管理4個主要成分。
當嵌入式操作系統采用微內核結構時,放到內核之外的功能有兩種存在形式:一是作為服務任務存在;二是以庫函數的形式存在。
當內核外的功能以服務任務的形式存在時,在被服務的任務與提供服務的任務之間將建立一種“客戶/服務器”關系。當一個任務有某種服務需求時,可以向服務任務發出請求,并由服務任務,而不是內核中的模塊為發出請求的任務提供服務。但這個過程的細節通常被隱藏了起來,發出請求的任務以為服務請求交給了內核,而得到的服務也由內核提供。
以系統調用open為例,可以采用如下的實現方法:當用戶任務調用open要求打開一個文件時,內核將使該用戶任務進入阻塞狀態,然后以此任務的名義向文件服務任務發送一個消息。當文件服務任務接收到這個消息并完成所要求的操作以后,發回一個應答消息,內核在接收到這一消息后,使請求打開文件的用戶任務進入就緒狀態,并根據文件服務任務發回的消息決定本次系統調用的返回值。
當內核的功能由服務任務完成時,雖然邏輯上應用軟件的任務仍在高層,服務任務還是在低層為其提供服務,但是結構上則不再遵循同樣的關系,因為提供服務的任務與用戶任務處在同一層次上。當然,也可以讓應用任務知道服務任務的存在,直接向服務任務發出服務請求。但即使是這樣,也要通過內核作為中介來傳遞消息并加以協調,因為任務通信機制需要由內核來提供。
一體化的內核好比是一個實力雄厚的工程承包商,承接的所有工程都靠自身的力量來完成。微內核好比是一個自身沒有多大施工能力的承包代理,除去必要的管理工作之外,一般的工作都是分包給其他的公司來完成。
當內核外的功能以庫函數的形式存在時,庫函數可以是靜態鏈接的庫函數或動態鏈接的庫函數。UNIX/Linux上的.a文件和Windows上的.lib文件都是靜態鏈接庫。應用軟件在編譯/連接階段就靜態地將這種庫函數的可執行代碼鏈接進它的可執行文件中,所以在每個可執行文件中都有一份庫函數的副本。UNIX/Linux上的.so文件、Windows上的.dll文件都是動態鏈接庫。應用軟件在運行時才動態地與這種庫函數建立鏈接,并且所有的應用軟件都共享庫函數的同一份副本。
服務任務和庫函數兩種組織核外功能的方法并不互相排斥,可以混合使用,或者以前者為主,以后者作為補充。
相對于一體化結構的操作系統,微內核結構的操作系統有以下一些優點。
① 操作系統內核小,且簡單,所以容易理解,容易維護。
②各種系統模塊(如文件系統)、設備驅動程序、乃至中斷服務程序,都可以作為獨立的任務來開發,相互間的關系簡單,便于調試,并且容易在其他環境下模擬。因此整個系統的開發有一條漸進的途徑。
③ 系統配置靈活方便。從商業的角度還可以把內核和各種服務任務或庫函數分別銷售,讓用戶根據具體需要選購,而且也有利于其他軟件開發商開發各種第三方軟件。
④ 由于操作系統的內核很小,所以執行內核代碼的時間十分短暫。這樣,基本消除了因為執行內核代碼而產生的不可搶占問題,提高了系統的實時性。可以說,微內核天生就是可搶占的。許多嵌入式操作系統之所以宣稱“可搶占”,就是因為采用了微內核結構的原因。
相對于一體化結構的操作系統,微內核結構的操作系統又有以下一些缺點。
① 系統效率有時會有所降低。例如,如果將對于外部事件的處理放到內核之外,微內核在響應了外部事件所引起的中斷以后,需要進行任務調度。當負責處理外部事件的服務任務被調度程序選中之后,外部事件才能得到處理。因此,原本只有一個中斷延遲,現在卻又增加了一個調度延遲。盡管因為“可搶占”性的增強會使調度延遲得到一定程度的縮減,但系統的綜合響應速度卻很可能還會有所下降。
② 系統安全性會有所降低。例如,文件系統的安全性無疑是信息安全中的一個關鍵問題,如果把文件系統放到內核之外,顯然更容易被外來的入侵所攻破,出現安全漏洞。
2.1.5 嵌入式操作系統的組成
各種嵌入式操作系統的具體組成有很大的不同,特別是微內核結構的嵌入式操作系統與一體化結構的嵌入式操作系統有比較顯著的差別。但對于同樣采用微內核結構的系統而言,其組成則有一定的共同之處。如圖2.9所示,當一個嵌入式操作系統采用微內核結構,并且內核之外的功能以服務任務的形式存在時,其組成可分為硬件抽象層、操作系統內核、核外服務、應用程序接口等幾個部分。
1. 硬件抽象層
硬件抽象層用于屏蔽不同硬件的特征。向下它與嵌入式系統的硬件直接打交道,向上它對操作系統內核中的各個模塊提供一個統一的接口,增強了系統的可移植性。當需要將嵌入式操作系統從一個硬件平臺移植到另一個硬件平臺上時只需修改硬件抽象層的程序代碼。

圖2.9 嵌入式操作系統的組成
2. 操作系統內核
像上面曾經討論過的那樣,任務管理、內存管理、任務通信和中斷管理等幾部分功能通常只能放在操作系統內核中,而其他的一些功能,如文件管理、電源管理、輸入/輸出管理、“看門狗”等,雖然可以放在內核之中,但也可以放在內核之外,以服務任務或庫函數的形式存在。
3. 核外服務
一般情況下,文件管理、電源管理、輸入/輸出管理、“看門狗”等一些功能應當由內核之外的服務任務來實現。中斷管理雖然需要由內核來實現,但這不意味著中斷服務程序要承擔所有的中斷處理工作,完全可以把一些處理工作放在一個專門的中斷服務任務中。每當有中斷請求發生時,內核中的中斷服務程序只要把與中斷有關的信息通知中斷服務任務(可以通過內核支持的某一種任務通信方式),并使這個任務進入就緒狀態,具體的處理工作就可以由這個中斷服務任務去完成(中斷服務任務的優先級一般都很高,進入就緒狀態后馬上就會被調度運行)。
一些嵌入式操作系統以核外服務的形式提供窗口和網絡方面的功能。但這些功能比較獨立,按照經典理論它們不是操作系統的一部分,所以還是把它們歸類于支撐軟件比較合理。
4. 應用程序接口
應用程序接口提供一系列供應用程序開發者調用的功能。應用程序開發者通過應用程序接口達到使用嵌入式操作系統的目的。應用程序接口還可以進一步分為多個部分,包括操作系統所提供的系統調用和建立在系統調用基礎上的庫函數。
2.1.6 嵌入式操作系統的類型
嵌入式操作系統的種類很多,分類方法也是多樣化的,下面從供應方式、實時性、歷史淵源等幾個角度對其進行分類并介紹它們的特點。
從嵌入式操作系統的供應方式上可將其分為商用嵌入式操作系統和開源嵌入式操作系統兩類。
商用嵌入式操作系統一般功能穩定、可靠、有完善的技術支持和售后服務、輔助工具齊全。例如,WindRiver公司的VxWorks、Palm Computing公司的PalmOS、微軟公司的Windows CE和凱思昊鵬公司的Hopen都是商用嵌入式操作系統。
開源嵌入式操作系統在價格方面有優勢,此外由于應用軟件開發者可以獲得操作系統源代碼,這給開發工作帶來了很大方便。但開源嵌入式操作系統的缺點也非常明顯,主要表現是技術支持差、系統穩定性相對較差。因此,使用這類嵌入式操作系統對開發者有較高的要求。雖然目前有一些公司可以為開源嵌入式操作系統提供技術服務,但購買這種服務的費用并不低于購買商用嵌入式操作系統。開源嵌入式操作系統的典型代表是嵌入式Linux。
從嵌入式操作系統的實時性上可將其分為實時嵌入式操作系統和非實時嵌入式操作系統兩類。
實時嵌入式操作系統的特征是能滿足應用程序對時間的限制和要求。它主要用在控制、軍事、通信等領域。例如,WindRiver公司的VxWorks、QNX Software Systems Europe公司的QNX、Accelerated Technology公司的Nucleus都是實時嵌入式操作系統。
非實時嵌入式操作系統不關心單個任務的響應時間,它的系統平均性能一般較好,比較適合用在消費類電子產品中,如個人數字助理(PDA)、機頂盒、電子書、網絡電話等。非實時嵌入式操作系統的典型代表是較早版本的Windows CE。
從嵌入式操作系統的歷史淵源上可將其分為PC型嵌入式操作系統和非PC型嵌入式操作系統兩類。
PC型嵌入式操作系統是由個人計算機或服務器上的操作系統演化來的嵌入式操作系統。例如,微軟公司的Windows CE、嵌入式Linux等。這類操作系統經過在個人計算機或服務器上的長期運行,技術比較成熟,相關軟件的開發方式用戶比較熟悉,同時也積累了豐富的開發工具和應用軟件。
非PC型嵌入式操作系統是專門為嵌入式系統開發的操作系統。例如,WindRiver公司的VxWorks和OSEKworks、Psion公司的Symbian、UC Berkeley公司的TinyOS等。這類操作系統一般針對某些固定的應用需求而設計,較多地應用在對系統的可靠性和實時性要求很高的領域。