嵌入式Linux實時技術(shù)改進與實現(xiàn)
(1).No Forced Preemption (Server),這種模式等同于沒有使能搶占選項的標(biāo)準(zhǔn)內(nèi)核,主要適用于科學(xué)計算等服務(wù)器環(huán)境。
(2).Voluntary Kernel Preemption (Desktop),這種模式使能了自愿搶占,但仍然失效搶占內(nèi)核選項,它通過增加搶占點縮減了搶占延遲,因此適用于一些需要較好的響應(yīng)性的環(huán)境,如桌面環(huán)境,當(dāng)然這種好的響應(yīng)性是以犧牲一些吞吐率為代價的。
(3).Preemptible Kernel (Low-Latency Desktop),這種模式既包含了自愿搶占,又使能了可搶占內(nèi)核選項,因此有很好的響應(yīng)延遲,實際上在一定程度上已經(jīng)達到了軟實時性。它主要適用于桌面和一些嵌入式系統(tǒng),但是吞吐率比模式2更低。
(4).Complete Preemption (Real-Time),這種模式使能了所有實時功能,因此完全能夠滿足軟實時需求,它適用于延遲要求為100微秒或稍低的實時系統(tǒng)。
實現(xiàn)實時是以犧牲系統(tǒng)的吞吐率為代價的,因此實時性越好,系統(tǒng)吞吐率就越低。
3、中斷線程化
中斷線程化是實現(xiàn)Linux實時性的一個重要步驟,在Linux標(biāo)準(zhǔn)內(nèi)核中,中斷是最高優(yōu)先級的執(zhí)行單元,不管內(nèi)核當(dāng)時處理什么,只要有中斷事件,系統(tǒng)將立即響應(yīng)該事件并執(zhí)行相應(yīng)的中斷處理代碼,除非當(dāng)時中斷關(guān)閉。因此,如果系統(tǒng)有嚴(yán)重的網(wǎng)絡(luò)或I/O負載,中斷將非常頻繁,后發(fā)生的實時任務(wù)將很難有機會運行,也就是說,毫無實時性可言。中斷線程化之后,中斷將作為內(nèi)核線程運行而且賦予不同的實時優(yōu)先級,實時任務(wù)可以有比中斷線程更高的優(yōu)先級,這樣,實時任務(wù)就可以作為最高優(yōu)先級的執(zhí)行單元來運行,即使在嚴(yán)重負載下仍有實時性保證。
中斷線程化的另一個重要原因是spinlock被mutex取代。中斷處理代碼中大量地使用了spinlock,當(dāng)spinlock被mutex取代之后,中斷處理代碼就有可能因為得不到鎖而需要被掛到等待隊列上,但是只有可調(diào)度的進程才可以這么做,如果中斷處理代碼仍然使用原來的spinlock,則spinlock取代mutex的努力將大打折扣,因此為了滿足這一要求,中斷必須被線程化,包括IRQ和softirq。
中斷線程化的實現(xiàn)方法是:對于IRQ,在內(nèi)核初始化階段init(該函數(shù)在內(nèi)核源碼樹的文件init/main.c中定義)調(diào)用init_hardirqs(該函數(shù)在內(nèi)核源碼樹的文件kernel/irq/manage.c中定義)來為每一個IRQ創(chuàng)建一個內(nèi)核線程,IRQ號為0的中斷賦予實時優(yōu)先級49,IRQ號為1的賦予實時優(yōu)先級48,依次類推直到25,因此任何IRQ線程的最低實時優(yōu)先級為25。原來的do_IRQ被分解成兩部分,架構(gòu)相關(guān)的放在類似于arch/*/kernel/irq.c的文件中,名稱仍然為do_IRQ,而架構(gòu)獨立的部分被放在IRQ子系統(tǒng)的位置kernel/irq/handle.c中,名稱為_do_IRQ。當(dāng)發(fā)生中斷時,CPU將執(zhí)行do_IRQ來處理相應(yīng)的中斷,do_IRQ將做了必要的架構(gòu)相關(guān)的處理后調(diào)用_do_IRQ。函數(shù)_do_IRQ將判斷該中斷是否已經(jīng)被線程化(如果中斷描述符的狀態(tài)字段不包含SA_NODELAY標(biāo)志說明中斷被線程化了),如果是將喚醒相應(yīng)的處理線程,否則將直接調(diào)用handle_IRQ_event(在IRQ子系統(tǒng)位置的kernel/irq/handle.c文件中)來處理。對于已經(jīng)線程化的情況,中斷處理線程被喚醒并開始運行后,將調(diào)用do_hardirq(在源碼樹的IRQ子系統(tǒng)位置的文件kernel/irq/manage.c中定義)來處理相應(yīng)的中斷,該函數(shù)將判斷是否有中斷需要被處理(中斷描述符的狀態(tài)標(biāo)志IRQ_INPROGRESS),如果有就調(diào)用handle_IRQ_event來處理。handle_IRQ_event將直接調(diào)用相應(yīng)的中斷處理句柄來完成中斷處理。
如果某個中斷需要被實時處理,它可以用SA_NODELAY標(biāo)志來聲明自己非線程化,例如:系統(tǒng)的時鐘中斷就是,因為它被用來維護系統(tǒng)時間以及定時器等,所以不應(yīng)當(dāng)被線程化。
static struct irqaction irq0=
{ timer_interrupt, SA_INTERRUPT | SA_NODELAY, CPU_MASK_NONE, timer, NULL, NULL};
這是在靜態(tài)聲明時指定不要線程化,也可以在調(diào)用request_irq時指定,如:
request_irq (HIGHWIRE_SMI_IRQ,highwire_smi_interrupt,SA_NODELAY, System Management Switch, NULL))
對于softirq,標(biāo)準(zhǔn)Linux內(nèi)核已經(jīng)使用內(nèi)核線程的方式來處理,為了使其易于被搶占,改進實時性,具體的修改包括:把ksoftirqd的優(yōu)先級設(shè)置為nice值為-10,即它的優(yōu)先級高于普通的用戶態(tài)進程和內(nèi)核態(tài)線程,但它不是實時線程,因此這樣一來softirq對實時性的影響將顯著減小。在處理軟中斷期間,搶占是使能的,這使得實時性更進一步地增強。在處理軟中斷的函數(shù)_do_softirq中,每次處理完一個待處理的軟中斷后,都將調(diào)用cond_resched_all(),這顯著地增加了調(diào)度點數(shù),提高了整個系統(tǒng)的實時性。
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)
評論