嵌入式實時Linux的技術(shù)研究
中斷管理的第二個關(guān)鍵部分即是系統(tǒng)是否允許中斷嵌套的能力,也就是說,當(dāng)響應(yīng)一個中斷時,是否允許其它更高優(yōu)先級的中斷打斷,等更高優(yōu)先級的中斷處理完畢,是否還能恢復(fù)原來中斷處理的現(xiàn)場。通過這項功能,系統(tǒng)設(shè)計者可以指示外部中斷的優(yōu)先級,從而確保高優(yōu)先級的任務(wù)能及時處理。Linux允許中斷嵌套,它是利用外部中斷管理器來設(shè)置中斷的優(yōu)先級的。在Linux的中斷處理程序的啟動過程中,它一般調(diào)用語句mask_and_ack_8259A(irq);來設(shè)置8259中的int_mask寄存器.使優(yōu)先級比此中斷低的中斷不能發(fā)生。在中斷處理程序離開時,調(diào)用enable_8259A_irq(irq)來改回8259中int_mask寄存器原來的值。因此,intr類中斷的優(yōu)先級由硬件8259來決定.
由此可見,Linux的中斷管理部分具有高效的特點,已經(jīng)可以滿足許多軟實時任務(wù)的要求。
(2)進(jìn)程搶先調(diào)度
在許多控制系統(tǒng)中,實時控制軟件是非常簡單的,可以直接寫入中斷處理程序中與一個特定的中斷聯(lián)系起來。還有一些就不那么簡單了,必須開啟專門的用戶進(jìn)程為它服務(wù)。
這時當(dāng)這個高優(yōu)先級的進(jìn)程提交時,如有其它進(jìn)程正在運行,它就必須打斷正在運行的進(jìn)程。若正在運行的進(jìn)程運行在用戶態(tài),系統(tǒng)一般允許它被打斷且執(zhí)行其它優(yōu)先權(quán)高的進(jìn)程,若正在運行的進(jìn)程運行在系統(tǒng)態(tài),則此時是否允許被打斷決定了系統(tǒng)是搶先式的還是非搶先式的。
Linux就是一個非搶先式的操作系統(tǒng),在用戶執(zhí)行系統(tǒng)調(diào)用時,不允許其它進(jìn)程的調(diào)度,這樣就影響了系統(tǒng)的響應(yīng)度。一個真正的搶先式的操作系統(tǒng)允許正在系統(tǒng)狀態(tài)下的當(dāng)前進(jìn)程被打斷,然后進(jìn)程切換回來時還能繼續(xù)從剛才的執(zhí)行點繼續(xù)下去。但某些關(guān)鍵部分的代碼段。系統(tǒng)必須保證其原子性,并防止重入。通常有如下幾種方法:
在關(guān)鍵代碼斷前關(guān)閉中斷,等其執(zhí)行完畢之后再將中斷打開; 設(shè)計一個信號量.在關(guān)鍵代碼段之前加鎖,在其后解鎖;
在系統(tǒng)代碼中保證安全的地方加入切換進(jìn)程的代碼switch(),防止該進(jìn)程長久占用CPU,允許調(diào)度其它進(jìn)程; 在關(guān)鍵代碼段加入一個switchaccept標(biāo)志,開始該代碼段時。將此標(biāo)志置為否.離開時再置回原來的值.這樣在執(zhí)行該段代碼時,即使進(jìn)程調(diào)度器被激活,它也會先檢查此標(biāo)志。若為否,則返回,并不進(jìn)行進(jìn)程切換。
(3)進(jìn)程調(diào)度策略
第三個影響系統(tǒng)響應(yīng)速度的關(guān)鍵部分就是進(jìn)程調(diào)度的策略。對于一個實時性能強的操作系統(tǒng)來說,系統(tǒng)必須規(guī)定不同進(jìn)程的優(yōu)先級,并把優(yōu)先級作為唯一的進(jìn)程選擇的標(biāo)準(zhǔn)。Linux的后期版本參照Posixl.b標(biāo)準(zhǔn),在某些方面已經(jīng)具備了一些實時操作系統(tǒng)的特性。Linux有兩種類型的進(jìn)程:一般進(jìn)程和實時進(jìn)程,它可以通過sched_setscheduler系統(tǒng)調(diào)用設(shè)置實時進(jìn)程。實時進(jìn)程比所有一般進(jìn)程的優(yōu)先級高,Linux設(shè)置實對進(jìn)程的權(quán)重為它的counter值加1000;設(shè)置一般進(jìn)程的權(quán)重為counter。因此,實時進(jìn)程總會被認(rèn)為是最值得運行的進(jìn)程。
然而,Linux核心的設(shè)計主要集中在應(yīng)用程序的吞吐量上。追求吞吐量的必然結(jié)果,就是Linux調(diào)度器運用一種公平共享的策略保證所有的進(jìn)程得到平均的CPU資源。而且,Linux的進(jìn)程調(diào)度器只是簡單地將標(biāo)有實時標(biāo)志的進(jìn)程的權(quán)重加1000,至于實時進(jìn)程間的輕重緩急還沒有周密的完整的設(shè)計。因此,Linux的進(jìn)程調(diào)度器還遠(yuǎn)不能稱作是一個真正的實時進(jìn)程凋度器。
4 擬采用的策略
根據(jù)以上分析的特點,我們決定主要從以下4個方面來修改Linux的核心代碼。
(1)在內(nèi)核中插入搶先點 由于Linux是一個非搶先式的操作系統(tǒng)。因此當(dāng)一個實時進(jìn)程提交時,很可能因為當(dāng)前的進(jìn)程正處于核心態(tài)不能被打斷而不能得到及時的處理。因此有必要在Linux內(nèi)核中插入搶先點,使實時進(jìn)程得到處理。根據(jù)上一節(jié)分析的特點,太體有4種方法可供選擇。權(quán)衡這4種方法的利弊,我們決定采用第4種方法,即在關(guān)鍵代碼段加入一個switchaccept標(biāo)志,開始該代碼段時,將此標(biāo)志置為否.離開時再置回原來的值。這種方法比采甩semaphore的好處是,如果采用許多種semaphore的話.要考慮是否會產(chǎn)生死鎖的問題。比采用鎖中斷的好處是.將中斷鎖住將丟失中斷,而這樣不會。而以固定的周期加switch語句顯然有失靈活性。這樣.采用這種方法,需要我們分析Linux所有系統(tǒng)調(diào)用的代碼,畫出其結(jié)構(gòu)流程圖。分析出哪些部分是關(guān)鍵部分,也即不允許置入的部分。在關(guān)鍵代碼前后更改switchaccept標(biāo)志。這項工作比較艱巨。同時修改進(jìn)程調(diào)度器,使其判斷switchaccept標(biāo)志來決定是否執(zhí)行進(jìn)程切換。
(2)修改進(jìn)程調(diào)度器Linux的進(jìn)程調(diào)度器雖然已經(jīng)具有一定的實時性能,但還遠(yuǎn)遠(yuǎn)達(dá)不到真正實時調(diào)度器的標(biāo)準(zhǔn),因此需要修改其進(jìn)程調(diào)度器,必要的話可讓Linux運行在兩種模式下,實時模式和分時模式。可設(shè)計一些相關(guān)的系統(tǒng)調(diào)用,并在實時進(jìn)程提交時,將系統(tǒng)轉(zhuǎn)化為實時模式,當(dāng)實時進(jìn)程結(jié)束時,再轉(zhuǎn)化為分時模式。
(3)Linux的中斷管理根據(jù)前面分析過的,Linux的中斷管理及時地將緊要的任務(wù)完成后,將其余不重要的緩慢的任務(wù)放置在任務(wù)隊列中,等到系統(tǒng)空閑(cpu idle())或系統(tǒng)調(diào)用等返回時再完成這些任務(wù),這樣就提高了系統(tǒng)的響應(yīng)速度,同時,Linux還支持中斷嵌套。因此,不再對其作太大改動。
(4)鎖定內(nèi)存 在本項目的規(guī)劃中本打算實現(xiàn)Linux鎖內(nèi)存的功能,使優(yōu)先權(quán)高的進(jìn)程在內(nèi)存中的數(shù)據(jù)不被換出,從而提高實時進(jìn)程的運行速度。然而,在分析了Linux代碼后,發(fā)現(xiàn)后來版本的Linux已通過系統(tǒng)調(diào)用sys mlock實現(xiàn)了此項功能。
5 結(jié)束語
采用上述方法修改了內(nèi)核代碼后,由于每個修改方案都是有一定的代價的,它在增加了系統(tǒng)響應(yīng)速度的同時也在某種程度上降低了系統(tǒng)的整體效率,比如說將內(nèi)核設(shè)置成可搶先的,在進(jìn)程頻繁的切換過程中也要消耗一定的cpu處理時間。因此,還需要對各種解決方案進(jìn)行測試、比較。另外,為了減少嵌入式Linux自身的長度,在存儲管理部分對虛擬內(nèi)存也應(yīng)作進(jìn)一步的處理。
評論