1.中斷響應時間
實時操作系統的意義就在於能夠在確定的時間內處理各種突發的事件,而中斷是這些事件、系統搶占調度的觸發點,中斷何時得到處理反應了系統的基本實時性能,因而衡量嵌入式實時操作系統的最主要、最具有代表性的性能指標參數無疑是中斷響應時間。
中斷延遲時間是指從接收到中斷信號到操作系統做出響應,並完成進入中斷服務例程所需要的時間。中斷延遲時間=最大關中斷時間+硬件開始處理中斷到開始執行中斷服務例程第一條指令之間的時間。
通俗地說:中斷產生到內核執行中斷處理程序第一條指令的時間。
2. x86中斷處理和xenomai中斷管理機制
2.1.x86中斷機制
X86 系統中有256個vector,用來識別中斷或異常的類型,vector 0-31處理器保留,有固定的用途, 從32到255的vector編號被指定為用戶定義的中斷,不被處理器保留。 這些中斷通常分配給外部I / O設備(部分固定為APIC中斷),以使這些設備能夠將中斷發送到處理器,每個vector的處理程序都保存在一個特殊的位置--IDT(中斷描述符表),IDT的基地址保存在寄存器IDTR,在64位x86下IDT是一個16字節描述的數組(32位系統為8字節),當中斷發生時CPU將vector乘以16(32位系統是乘以8)來找到IDT中的對應條目idt_data,然后根據條目信息跳轉到處理入口執行中斷和異常處理。
2.2.xenomai中斷管理機制
(1)硬件中斷
Xenomai是一個RTOS,與linux共存,為了使Xenomai能夠保持可預測的延遲(硬實時),必須阻止Linux內核直接處理中斷,先將中斷重定給Xenomai處理,然后才是Linux內核。為此在底層增加一個微內核來實現。微內核充當虛擬可編程中斷控制器,分離Linux和Xenomai之間的中斷掩碼,該微內核稱為中斷管道(I-Pipe),中斷的分發和實時性由I-Pipe來保障,I-Pipe在系統中的位置如下所示。
Linux和xenomai在I-ipipe上稱為domain, I-Pipe將Linux和xenomai系統組織到兩個域中,其中xenomai域的優先級高於Linux域。這兩個域共享一個地址空間,允許來自xenomai的線程調用 Linux 內核域中的服務。 I-Pipe 以 domain 優先級順序調度中斷。 Xenomai 被設置為最高優先級域,並將首先接收中斷。
如上圖所示,當cpu接收到一個中斷后,通過IDT表中的中斷入口進入I-Pipe處理邏輯,I-Pipe會先判斷該中斷是否是實時系統的中斷(實時域中斷),如果是,直接執行其中斷服務函數。如果不是的話會將該中斷保存到Linux域中斷管理中記錄,待xenomai 讓出cpu后,Linux域執行時逐一從log中取出按Linux的中斷入口去處理。
用於記錄中斷的log的是bitmap:
(2)虛擬中斷
ipipe為了 xenomai 與 linux 之間交互時,如域切換調度、實時與非實時通訊等,為保證xenomai的實時性,引入了虛擬中斷機制 。需要注意的是虛擬中斷和常規 softirq 本質上不同,不能混淆 , softirq 只存在 linux 中,ipipe虛擬中斷更近似於硬件中斷,但不是硬件觸發,由內核之間需要處理緊急任務時向另一個內核發送,除產生源不同外,ipipe將虛擬中斷和硬件中斷同等對待,ipipe處理虛擬中斷與處理硬件中斷流程一致。
虛擬中斷注冊和其他中斷注冊是一樣的,只是這個中斷號是通過函數ipipe_alloc_virq()
來分配,由函數ipipe_free_virq()釋放。比如__ipipe_printk_virq
,當 xenomai 需要調用 linux 的打印輸出時,只需要在 xenomai 中執行ipipe_post_irq_root(__ipipe_printk_virq)
(給低優先級的 Linux 發送中斷),然后就會在 Linux 上下文中執行__ipipe_flush_printk()
,進行打印 xenomai 輸出的內容,進而避免打印影響xenomai實時性。
相反,Linux可以通過虛擬中斷觸發 xenomai 上的一些活動,只需要在 Linux上下文中執行ipipe_post_irq_head(virq_xxx)
(給 xenomai 發送中斷),xenomai 就會很快執行相應操作。此外虛擬中斷還可以本內核觸發本內核虛擬中斷。不管是虛擬中斷還是硬件中斷, xenomai 優先級都比 Linux 高。
4.中斷響應測試設計
4.I-pipe內核間虛擬中斷
注冊一個RTDM設備,分配一個虛擬中斷,將這個虛擬中斷號(virq)與中斷處理函數(ISR) 通過RTDM接口注冊到xenomai域。
測試時發送前讀取TSC的值,轉換為時間t0,使用ipipe_post_irq_head(virq)
發送中斷,在中斷處理函數中讀取時間t1,時間T= t1- t0就是虛擬中斷響應時間,測試流程如下。
上述過程用戶任務定時測試K次,就可以得到K次中斷響應時間。
4.1.硬件中斷
(1)測試方法
由於硬件中斷的特殊性,測試方法有很多,常用的方式有:
- 使用外部設備通過GPIO引腳觸發中斷,中斷服務程序中翻轉GPIO電平,外部通過示波器或者MCU來反映中斷響應時間。缺點:需要外部設備、外設操作速度慢、x86平台上Gpio子系統xenomai 支持不是很好(注:該文寫於2019年,目前xenomai3.2-rc+已對部分intel平台支持實時GPIO驅動,xenomai也提供了GPIO測試程序)。
- 使用硬件定時器周期觸發中斷,中斷處理函數中讀取時間,讀取到的時間減去定時器觸發中斷的時間即中斷響應時間。
- SMP架構可通過可編程中斷控制器來產生中斷,記錄中斷發送時時間t0,中斷處理函數中讀取時間t1,時間T= t1- t0就是硬件中斷響應時間。(本方案)
(2)測試設計
X86 SMP系統中,當外設向CPU發出中斷,中斷不會直接發送到CPU,有一個高級可編程中斷控制器(APIC)負責順序處理來自對各設備的多個中斷請求,APIC由Local APIC和I/O APIC兩部分組成。
- Local APIC位於每個CPU核心上,負責本CPU特定的中斷配置,通常用來管理來自APIC-timer、熱傳感器和其他此類鏈接本地I/O設備的中斷。
- I/O APIC提供多處理器中斷管理,用於CPU核之間分配外部中斷,按一定規則將外部中斷處理成中斷消息發送到Local APIC。
根據LAPIC可編程產生中斷的特性,使用APIC來產生中斷,LAPIC的中斷命令寄存器(ICR)是一個64位寄存器(見圖),它允許處理器上運行的軟件指定處理器中斷(IPI)並將其發送到系統中的其他處理器。要發送IPI,軟件必須設置ICR以指示要發送的IPI消息的類型以及目標處理器。寫入ICR的動作會導致IPI被發送。
根據以上信息,我們利用寫ICR寄存器來向CPU產生一個中斷代替外部硬件觸發來測是xenomai 中斷響應時間。
在每個CPU中,每個中斷和異常分配一個數來標識,稱為vector number,在X86體系中中斷向量范圍為0-255,最多表示256個中斷,用一個8位的無符號整數來表示,前32個vector為系統保留,32-255可由用戶(OS)動態分配。
所以需要選出一個未使用的vector來作為本次測試的中斷號,
作為測試中斷號,對應的修改內核源碼添加中斷號,以及中斷服務程序 ipipe_inttest_interrupt
,ipipe_inttest_interrupt
將中斷號壓棧后跳轉至ipipe層做分發,ipipe會根據中斷注冊信息遞交給Linux或xenomai處理。
整個測試與虛擬中斷測試類似流程如下:
- 安裝測試RTDM驅動,將中斷處理函數
xnintr_test_handler()
注冊到xenomai域,中斷處理函數中讀取當前TSC時間t0。 - 應用程序發起一次中斷響應測試。
- 內核中,測試驅動讀取當前TSC時間t0,然后寫LAPIC ICR寄存器向目標CPU產生中斷。
- 目標CPU保存當前上下后執行中斷服務程序ISR(ipipe_inttest_interrupt)。
- ISR(ipipe_inttest_interrupt)調用
__ipipe_handle_irq
讓ipipe分發中斷,ipipe根據中斷注冊信息讓xenomai執行注冊的中斷處理程序xnintr_test_handler
。 xnintr_test_handler
中讀取當前TSC時間t1,后返回。- 測試驅動將本次測試數據t1、t0拷貝到用戶空間。
- 用戶程序計算時間測,統計測試結果輸出,跳轉到第2步繼續下一輪測試。
ctx-> handler = (ipipe_irq_handler_t)xnintr_test_handler;
err = ipipe_request_irq(&xnsched_realtime_domain, ctx->irq, (ipipe_irq_handler_t)ctx->handler, (void *)ctx, __ipipe_ack_apic);
測量中斷是從本CPU LAPIC發送給本CPU處理;核間中斷響應時間為本CPU LAPIC發送中斷給其他CPU。但是ipipe沒有實現本CPU給本CPU發送中斷的接口,所以還需要實現這個接口ipipe_send_ipi_curr()
。
5.測試結果
CPU和GPU同時加壓如下
#CPU
stress -c 10
#GPU
While true; do glmark2-es2 -size 800x450 > /dev/null; done&
While true; do glmark2-es2 -size 800x450 > /dev/null; done&
While true; do glmark2-es2 -size 800x450 > /dev/null; done&
While true; do glmark2-es2 -size 800x450 > /dev/null; done&
每項測試中斷產生周期和測試總時間如下。
5.1.I-pipe內核間虛擬中斷
無負載測試情況(單位us):
中斷周期及測試時長 | 最小 | 平均 | 最大 |
---|---|---|---|
100us 23h18m | 0.120 | 0.194 | 0.360 |
高負載測試情況(單位us):
中斷周期及測試時長 | 最小 | 平均 | 最大 |
---|---|---|---|
100us 24h | 0.168 | 0.216 | 0.324 |
5.2.硬件中斷
無負載測試情況(單位us):
中斷周期及測試時長 | 最小 | 平均 | 最大 |
---|---|---|---|
100us 24h | 0.223 | 0.401 | 1.819 |
高負載測試情況(單位us):
中斷周期及測試時長 | 最小 | 平均 | 最大 |
---|---|---|---|
100us 24h | 0.026 | 0.394 | 7.192 |
5.3.核間中斷
無負載測試情況(單位us):
中斷周期及測試時長 | 最小 | 平均 | 最大 |
---|---|---|---|
100us 23h35m | -0.155 | 0.137 | 4.179 |
不清楚為什么會有負值,初步猜測是不是每個CPU核的TSC不是同步的,或者亂序執行導致的,若哪位讀者知道,還望不吝賜教。
高負載測試情況(單位us):
中斷周期及測試時長 | 最小 | 平均 | 最大 |
---|---|---|---|
100us 21h | 0.086 | 0.184 | 4.288 |
版權聲明:本文為本文為博主原創文章,轉載請注明出處。如有問題,歡迎指正。博客地址:https://www.cnblogs.com/wsg1100/