1 嵌入式Linux系統分析 1.1 嵌入式系統 嵌入式系統(Embedded Systems)是以應用為中心,以計算機技術為基礎,軟件硬件可剪裁(可編程、可重構),適用于應用系統對功能、可靠性、成本、體積、功耗有嚴格要求的專用計算機系統。它一般由嵌入式微處理器、外圍硬件設備、嵌入式操作系統以及用戶的應用程序等四個部分組成,用于實現對其它設備的控制、監視或管理等功能。其中,嵌入式處理器是嵌入式系統中的核心部件。 1.2 實時操作系統 實時操作系統(RTOS,Real-Time Operation System)是指一個能夠在指定的時間范圍內完成特定的功能或者對外部的異步時間做出響應的操作系統。其操作的正確性不僅依賴于邏輯判斷和邏輯設計的正確程度,而且跟這些操作進行的時間有關。“在指定的時間范圍內”是這個定義的核心,也就是說,實時系統是對響應時間有嚴格要求的。這個定義要求了:系統應該有在事先定義的時間范圍內識別和處理離散事件的能力;系統能夠處理和存儲控制系統所需要的大量的數據。 1.3 嵌入式實時操作系統 由嵌入式系統的概念和特點可以看出,一個嵌入式系統對操作系統的可靠性、實時性都有很高的要求。尤其在嵌入式技術廣泛應用的工業控制、航空軍事等領域,對嵌入式操作系統的實時響應能力提出了非常嚴格的要求,哪怕出現很小的時間偏差,都有可能造成無法挽回的損失。這便是為何絕大多數嵌入式操作系統都采用實時操作系統的主要原因。實時操作系統應用到嵌入式領域,便出現了嵌入式實時操作系統,它是實時操作系統與嵌入式系統相結合的產物,具有實時性的同時又具有嵌入式系統的特點。 2 實時進程調度算法分析 2.1 Linux進程調度相關概念 進程調度分成兩個部分,一個是調度的時機,即什么時候調度;一個是調度的算法,即如何調度和調度哪個進程。 Linux進程調度時機: 調度時機是指在什么情況下運行調度程序來選擇進程運行。在Linux系統中調度程序是通過函數schedule()來實現的,這個函數被調用的頻率很高,由它來決定要運行的進程。 Linux調度時機主要分兩種情況:主動調度和被動調度。主動調度是指當進程狀態發生變化時直接調用schedule()來實現調度。被動調度是指當一個進程運行時間片到或就緒隊列中增加了一個進程,此時系統并不立即進行調度,而僅僅是將當前進程的調度標志位置1,當系統由核心態向用戶態轉變之前檢查當前進程的調度標志是否為1,若為1,則調用schedule()進行調度。 2.2 進程調度的原理 進程調度分成兩個部分,一個是調度的時機,即什么時候調度;一個是調度的算法,即如何調度和調度哪個進程。 調度程序運行時,要在所有可運行的進程中選擇最值得運行的進程。選擇進程的依據主要有進程的調度策略(policy)、靜態優先級(priority)、動態優先級(counter)、以及實時優先級(rt-priority)四個部分。首先,Linux從整體上區分為實時進程和普通進程,二者調度算法不同,實時進程優先于普通進程運行。進程依照優先級的高低被依次調用,實時優先級級別最高。 2.3 實時調度算法及缺陷 目前,實時調度算法主要可以分為三大類:時間驅動調度、優先級驅動調度、比例共享調度。三者各有優缺點,時間驅動調度、優先級驅動調度側重于硬實時任務,比例共享調度更為適合于軟實時任務,在網絡系統中應用較多。比例共享調度基本思想就是按照一定的權重比例對一組需要調度的任務進行調度,讓它們的執行時間與它們的權重成正比,是一種加權輪轉調度。 Linux進程采用的是多級輪轉調度算法,盡管Linux通過將進程劃分為實時進程和普通進程,按照優先級進行調度來實現實時的特性,但是僅能獲得秒級響應時間,Linux雖然給實時進程提供了較高的優先級,但是沒有加入時間限制,在高實時響應情況下還不能滿足要求。當進程進入核心態時,其它進程不管優先級多高也必須等待。 3 實時調度算法的改進 3.1 實時模型 作為實時系統調度算法應綜合考慮進程的價值和截止兩個概念,以保證實時進程在截止期內盡可能多地完成,在這里提出新的調度算法,改進Linux的實時性。 即:進程的優先級數(Vi)=該進程重要程度(Wi)+其緊迫度(pi/(d-Ti))*系數k。緊迫度的值越大,說明從時間上看這個任務越緊迫。優化后調度算法仍以進程的價值為基礎,同時也關注了完成進程的緊迫度,對于優先級相同的進程,采用FIFO調度策略。進程的價值越大說明該進程越重要,CPU越應完成它。 優化后調度算法仍以進程的價值為基礎,同時也關注了完成進程的緊迫度,對于優先級相同的進程,采用FIFO調度策略。進程的價值越大說明該進程越重要,CPU越應完成它,可是對一些價值和它相差不多,而緊迫度要比它大得多的進程來說,就不公平了。 例如,有兩個進程A,B同時提交,A的價值是1001,估計執行時間是1ms,相對截止期是5ms,B的價值是1000,估計執行時間是1ms,相對截止期是2ms,假設這里的系數因子k是10,則更應該執行進程B。這是因為進程A,B的價值相近,而B的緊迫度要比A的大一些,A的優先級=1001+1/5*10=1003,B的優先級=1000+1/2*10=1005,因此選擇B先運行,以防止B的夭折(注:Linux中實時進程的值設為從1000到1099,非實時進程的值設為從1到99,因此選擇系數因子k為10)優化后的調度算法依然采用時間片輪轉策略,依照Linux分配給進程的時間片為20次時鐘滴噠,也就是200ms =20*10ms。 3.2 結構定義 本文給出實時進程的結構定義,非實時進程依然采用原有的動態優先級調度策略,其結構定義略去。 3.3 鏈表定義 整個調度算法可以用雙鏈表來描述,即兩級隊列,分別用兩個指針指向。最初,這兩部分的頭指針都指向“0”,表明這兩個隊列均為空。其中實時進程的就緒等待隊列用一個循環單鏈表完成。 開始時的一級隊列,是新到的比當前運行進程優先級低的實時進程。如果一個進程由于時間片到時或被更高優先級任務搶占,根據它的優先級將其插入到第二級隊列。 若當前進程的時間片到時,CPU便選擇當前隊列中第二個節點的進程來判斷,如果它的緊迫度大于1的話,說明這個進程在規定時間內不能完成,它必定夭折,將其放入普通進程隊列中,再選擇鏈表的第三個節點判斷,如果緊迫度小于等于1便運行它,情況如圖1所示。 圖1 優化后調度算法的實時進程優先級表 當一級隊列為空時,二級隊列便升成一級隊列。 普通進程的調度通過單鏈表來實現。如果新來的進程屬于普通進程,則根據優先級高低插入普通隊列。只有實時隊列(一級和二級隊列)為空時,普通隊列才能被調度。 3.4 實時進程的調度策略算法描述 1)實時就緒隊列的初始化 #define LEN sizeof(TaskNode) 創建空鏈表: 2) 實時進程接收策略 #define K 10 void* pnow; pnew指向新來的實時進程,pnow指向當前運行的實時進程。 3)實時進程插入策略 說明:根據傳來的h值,決定在一級隊列h的值是Headl時還是在二級隊列h的值是Head2時中查找插入的合適位置。 當P是新來的任務時,h的值是Head1,p被括入一級隊列。p2是p1的后繼節點。在循環體中,當新來的進程P高于一級隊列的進程p2時,停止循環,將P插入到p1的后面;當p1等于Head2時,說明一級隊列的節點的優先級都比P節點的高,停止循環,把P插在p1的后面,則該節點便成了一級隊列的末尾。 當P是被搶占的任務時,h的值是Head2,p被插入二級隊列。在循環體中,當P的優先級高于二級隊列的進程p2時,停止循環,將P插入到p1的后面;如果P高于二級隊列的所有進程時,也會在p2指向Head時,因(*p).w<=(*p2) .w而停止,則該節點便成了二級隊列的末尾。因為((head1).w=-1,而任何進程的優先級數都不會小于1因此當p1,p2在這二級隊列中遍歷時,一定能有機會停止。 4) 調度等待鏈表中的一級隊列 當前進程完成或時間片到時,調度等待鏈表中的一級隊列中最前面的實時進程: 5)實時進程刪除策略 針對目前Linux實時系統調度算法中僅用進程的價值來確定優先級的現象,本文提出了綜合考慮進程的重要性和緊迫度來決定優先級的調度算法。算法將進程的截止期和價值兩個不相關的概念,通過公式結合在一起,用來計算就緒等待隊列中進程的優先級數。 該算法通過雙鏈表來實現。在CPU正常負載的情況下,優化后的調度算法體現了更優的實時性能。 |