Adeos在Xenomai體系結(jié)構(gòu)中的位置
你將會注意到Adeos接口直接暴露在硬件抽象層構(gòu)成了Xenomai核的基礎(chǔ)。因此,大多數(shù)對Adeos服務(wù)的要求從HAL層開始解決,它的實現(xiàn)能在相干arch/<archname>/hal目錄中找到,通用的位可以在arch/generic/hal下取得。看1看后者是最好的方法去理解Xenomai怎樣為了自己的目的利用Adeos的。
2.1. Xenomai的重要和次要域
Xenomai允許運行實時線程在嚴(yán)格內(nèi)核空間或在Linux線程地址空間。在文章剩下的部份,我們把后者稱作Xenomai線程,不會與常規(guī)Linux任務(wù)產(chǎn)生混淆(即便他們屬于 SCHED_FIFO 類)。Xenomai管理的所有線程
可以從實時nucleus中獲知。
支持實時線程排他的運行在內(nèi)核空間僅僅是1個共同核時期的1個回想,在用戶空間真實時支持來臨之前,當(dāng)實時利用僅能在嵌入到內(nèi)核模塊運行;這些特點Xenomai還保存著主要的目的是支持延遲利用,這里不做討論。
更有趣的是Xenomai對Linux有1個共生的方法;例如,這個使它不同于RTAI/LXRT的實現(xiàn)。以此為目的,Xenomai線程不但能像基于內(nèi)核的Xenomai線程運行在管線里最高優(yōu)先級域(即,主要域)的上下文中,而且可以運行在常規(guī)Linux空間(即,次要域),即便經(jīng)歷更高的調(diào)度延遲,仍被Xenomai當(dāng)作實時的。在Xenomai的術(shù)語中,前者被稱為運行在主要履行模式,而后者處于次要履行模式。
為了對運行在次要域的線程提供完全的實時支持,Xenomai需要實現(xiàn)以下幾點:
- 公共的優(yōu)先級模型。只能調(diào)度,我們需要1種方法使實時核和Linux內(nèi)核同享相同的優(yōu)先級模型相對線程同享控制。換句話說,1個Xenomai線程需要是自己的優(yōu)先級在任什么時候候嚴(yán)格生效,不管它當(dāng)前的域,在所有的Xenomai線程中。Xenomai采取稱為根線程可變優(yōu)先級的技術(shù),通過這個Linux內(nèi)核自動繼承被實時核控制的Xenomai線程的優(yōu)先級,這恰好產(chǎn)生在進(jìn)入次要域的時候。實際上,這意味著當(dāng)前運行在主要域的Xenomai線程沒有必要搶占運行在次要域中的線程,除非它們的有效優(yōu)先級確切更高。例如,上面的行動跟RTAI/LXRT相反,在RTAI/LXRT中線程遷移到Linux空間事實上會丟失它們實時有限級,通過繼承RTAI調(diào)度器定義的最低優(yōu)先級實現(xiàn)。也就是說,常規(guī)Linux任務(wù)隊Xenomai1無所知,這僅僅產(chǎn)生在屬于SCHED_FIFO的類中,當(dāng)與來自主要域的Xenomai線程競爭CPU時總會被搶占,即便他們依然會與運行在次要域中的Xenomai線程競爭優(yōu)先級明智。
- 程序履行時間的可預(yù)測性。當(dāng)1個Xenomai線程運行在Linux(即,次要)域,不管履行內(nèi)核還是利用代碼,它的時序不應(yīng)當(dāng)被非實時的Linux中斷活動攪動,通常來講被任何低優(yōu)先級、產(chǎn)生在內(nèi)核層的異步異步活動。1個簡單的方法來禁止后者產(chǎn)生的概率是當(dāng)Xenomai線程運行在Linux域時使Linux內(nèi)核保持中斷饑餓,因此沒有推延處理睬在這段時間內(nèi)觸發(fā)上半部中斷處理。使Linux內(nèi)核遭受中斷饑餓的方法是當(dāng)內(nèi)部需要中間Adeos域的時候阻塞他們,坐在被實時核和Linux內(nèi)核占用的中斷之間,在Xenomai術(shù)語中叫做中斷屏蔽。不管甚么時候Xenomai線程在Linux內(nèi)核空間被調(diào)用這個屏蔽都會被占用,在其它的情況下不同。需要注意的是屏蔽支持能被啟用/禁用在每一個線程基礎(chǔ)上,或在Xenomai構(gòu)建時系統(tǒng)范圍的基礎(chǔ)上;默許情況下對Xenomai是被禁用的并且不是內(nèi)建的。
- 細(xì)粒度的Linux內(nèi)核。為了從次要履行模式中取得最好,我們需要Linux內(nèi)核表現(xiàn)出最短的可能非搶占部份,因此在Xenomai線程運行在次要域變成準(zhǔn)備運行以后重調(diào)度的機(jī)會會盡快的被捉住。另外,這確保了Xenomai線程能在1個短的和有時間界的1段時間內(nèi)從主要域遷移到次要域,由于這個操作包括了到達(dá)1個內(nèi)核重調(diào)度點。由于這個,
2.2. 系統(tǒng)調(diào)用盜取
由于Xenomai實時API(即,skins)可以堆積在Xenomai的nucleus上,能將它們自己的1組服務(wù)導(dǎo)出給用戶空間Xenomai線程,必須有1種方法對適當(dāng)?shù)奶幚沓绦虻姆蛛x對應(yīng)的系統(tǒng)調(diào)用,而常規(guī)的系統(tǒng)調(diào)用都是在1起的。Xenomai攔截每個Xenomai線程需要處理的Xenomai或Linux域的系統(tǒng)調(diào)用圈套/異常。這通使用適當(dāng)?shù)腁deos定閱事件處理程序?qū)崿F(xiàn)。Xenomai使用這類能力來:
(1)將來自利用程序要求的實時服務(wù)分發(fā)給恰當(dāng)?shù)南到y(tǒng)調(diào)用途理程序;
(2)確保每個系統(tǒng)調(diào)用都會在其相應(yīng)的域中履行,不管是Xenomai還是Linux。
2.3. 中斷傳播
由于實時nucleus在管線的最前面,當(dāng)有感興趣的中斷來臨時在Xenomai域中的實時nucleus會第1個被通知,中斷被處理以后,nucleus會將該中斷標(biāo)記并傳遞到管線,如果必要終究會傳遞到Linux內(nèi)核域。當(dāng)被產(chǎn)生的中斷喚醒時,實時nucleus會在外部中斷處理程序返回后(以防中斷堆積)重新調(diào)度,并會轉(zhuǎn)換成它控制的可運行線程的最高優(yōu)先級。
當(dāng)沒有實時活動被阻塞時,Xenomai域會將CPU的控制權(quán)交給中斷屏蔽域。也就是說當(dāng)Xenomai域空閑時讓出CPU,當(dāng)Xenomai有事件處理時,搶占CPU。對中斷通過管線,Adeos有兩種傳播模式:隱式模式和顯示模式。隱式模式由系統(tǒng)自動傳播中斷,顯示模式需要手動傳播中斷。
3. 技能和訣竅
3.1 啟用/禁用中斷源
除能完全延遲1個域使不再有中斷能經(jīng)過它,直到它被明確的撤消延遲,Adeos允許在硬件層選擇性的禁用/重啟用中斷的實際源。
接收了這個盒子后,Adeos處理所有域的中斷制止的要求,包括Linux內(nèi)核的和實時核的。這意味著在硬件PIC層禁用中斷要求源,并鎖住從這個中斷源到當(dāng)前域在管線層的任何中斷的分發(fā)。相反的,啟用中斷意味側(cè)重新激活PIC層的中斷源,并允許從這個源到當(dāng)前域的進(jìn)1步分發(fā)。因此,1個想啟用1個中斷源的域必須是與制止這個中斷源的域是同1個,由于這樣的操作是域獨立的。
實際上,這意味著,成對使用時,rthal_irq_disable()和rthal_irq_enable()服務(wù)集成了構(gòu)成了Xenomai基礎(chǔ)的實時HAL內(nèi)相干Adeos的調(diào)用,必須由同1Adeos域解決。例如,如果1個實時中斷處理程序用rthal_irq_request()服務(wù)于某個中斷源連在1起,禁用中斷源使用rthal_irq_disable(),那末這個源將會被Xenomai域阻塞直到同1中斷源的rthal_irq_enable()被同1域調(diào)用。處理這個要求失敗將會致使受影響的中斷通道永久性丟失。
3.2. 域間同享中斷
1個在域間同享硬件中斷時誤用Adeos管線的典型例子以下:
void realtime_eth_handler (unsigned irq, void *cookie)
{
/*
* This interrupt handler has been installed using
* rthal_irq_request(), so it will always be invoked on behalf of
* the Xenomai (primary) domain.
*/
rthal_irq_disable(irq);
/* The Xenomai domain won't receive this irq anymore */
rthal_irq_host_pend(irq);
/* This irq has been marked as pending for Linux */
}
void linux_eth_handler (int irq, void *dev_id, struct pt_regs *regs)
{
/*
* This interrupt handler has been installed using
* rthal_irq_host_request(), so it will always be invoked on
* behalf of the Linux (secondary) domain, as a shared interrupt
* handler (Linux-wise).
*/
rthal_irq_enable(irq);
/*
* BUG: This won't work as expected: we are only unlocking the
* interrupt source for the Linux domain which is current here,
* not for the Xenomai domain!
*/
在上面的這個不工作的例子中,由于Xenomai對所有截獲的中斷總是使用顯示的傳播模式,接下來的以太網(wǎng)將會在Xenomai日志中被標(biāo)記為阻塞,等待Xenomai處理程序可能手動的將它傳播給Linux。但是由于中斷依然被Xenomai鎖在管線層(別忘了實際上沒有人從Xenomai域解決了期望的rthal_irq_enable()),這樣的是不會產(chǎn)生的,由于Xenomai處理程序直到鎖被移除才會運行的。因此,我們慶祝吧。
榮幸的是,對適當(dāng)?shù)耐碇袛嘤袀€方法,域間需要保持中斷源禁用直到終究處理結(jié)束(例如,處理電平動身的中斷是其中的1個問題):實際上,你不需要做任何事情,由于在把它傳遞給管線之前Adeos已屏蔽了來自PIC層的進(jìn)來任何中斷。因此,你僅僅需要處理你看到的合適相干域處理程序的中斷,并肯定在最后1個的時候使用rthal_irq_enable()來重啟用中斷源。不管什么時候Linux內(nèi)核是那些接收者之1,常規(guī)的內(nèi)核處理程序?qū)詣又貑⒂茫曰旧夏阒恍枰獡?dān)心在處理程序中調(diào)用rthal_irq_enable(),這個函數(shù)不會傳播傳進(jìn)來的中斷到Linux內(nèi)核。
特別的在x86體系結(jié)構(gòu)上,由于性能緣由,Adeos接收到的時鐘中斷將不會被屏蔽。這就是說,中斷源將不會是你想以任何方式禁用的,所以這不是個問題。
3.3. 中斷同享和延遲
但是,當(dāng)傳播通過全部管線保持屏蔽1個中斷源可能會增加延遲。
由于Adeos保證沒有由于中斷在任何域上堆積引發(fā)棧溢出的產(chǎn)生,并且由于它在動身中斷處理程序之前會延遲當(dāng)前階段,在Xenomai處理程序中沒有必要禁用中斷源。相反你乃至?xí)胫匦聠⒂盟@樣行將產(chǎn)生的中斷可以被立刻記錄下來,并且在當(dāng)前處理程序調(diào)用返回后回立即被處理。
所以,解決方法是以這類方法重寫先前的例子,以下:
void realtime_eth_handler (unsigned irq, void *cookie)
{
rthal_irq_enable(irq);
rthal_irq_host_pend(irq);
/* This irq has been marked as pending for Linux */
}
void linux_eth_handler (int irq, void *dev_id, struct pt_regs *regs)
{
/* process the IRQ normally. */
}
4. 結(jié)論
Adeos是相當(dāng)簡單的1段代碼,如果使用得當(dāng)包括了許多有趣的屬性。Adeos模型的主干是時間管線,正因如此,它提供了所有我們在Xenomai中需要的重要特點:
- 可預(yù)測的中斷延遲;
- 精確中斷虛擬化控制(每一個域和每一個中斷處理程序注冊,每一個域和每一個CPU的中斷屏蔽);
- 統(tǒng)1、優(yōu)先級和面向域的事件傳播模型;
- 1個通用和簡單的API來簡化客戶代碼的移植。
Xenomai使用這些特點來尋求Linux內(nèi)核帶來的實時服務(wù)的最大可能的集成。Xenomai的主要模式在最低的微秒即的延遲提供真的實時性能。另外,Xenomai在Linux未來演變中賭注,來改良內(nèi)核的整體粒度,例如PREEMPT_RT,因此次要模式仍在在肯定意義上的實時,即便是最壞情況下的延遲也是可測的。這就是為何Xenomai從第1天開始就努力工作來到達(dá)與Linux內(nèi)核高度集成的層次。斟酌共生,尋求共利。
5. 鏈接
- Karim Yaghmour's Adeos 提議: http://www.opersys.com/ftp/pub/Adeos/adeos.pdf
- 樂觀中斷保護(hù): http://citeseer.nj.nec.com/stodolsky93fast.html
- GNA上的Adeos工作目錄: https://gna.org/projects/adeos/
- 下載最新的Adeos補(bǔ)釘: http://download.gna.org/adeos/patches/
- Adeos API 參考手冊: http://home.gna.org/adeos/doc/api/globals.html