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