xenomai初探

Xenomai定義

一個real time的系統需要保證其工作在給定的時間限制之內完成。系統不需要以最快的速度完成任務,但是需要在指定的定時時間範圍內完成。
在這個前提條件下,realtime的系統任務完成時間是可確定的,根據運行的底層系統的不同,可以分爲以下兩類實時系統:

  • Soft Real Time:
    系統不一定每次都需要遵守deadline,但較多的deadline miss會導致服務質量降低。
  • Hard Real Time:
    系統能每次都能在deadline內完成任務。

Real time on Linux

  • PREEMPT_RT (in-kernel; single kernel)
    修改原本的 GNU/Linux 核心 (vanilla kernel),以減少non-preemptible section的方式,使其逐步改善 real-time 能力。

  • dual kernel (eg: RTLinux, RTAI, Xenomai)
    運作一個 real-time 核心,然後將修改後的的 GNU/Linux 核心程式視爲 real-time 核心的 idle task。

在xenomai中,dual kernel 就是 Xenomai 的 Nucleus / Cobalt Core 和 Linux kernel。Xenomai 改變整個系統架構,讓 ipipe -> xenomai scheduler 來預先處理 real-time task,而 Linux 則拉到上層成為一個task。這樣可以避免 Linux 因為龐大的架構而影響處理 real-time 的時間。

Xenomai系統架構

image
Xenomai是一個linux kernel的patch 藉由在底層增加一個架構 負責硬體與接收interrupt 並將interrupt 傳給上層的OS(這邊稱為domain)
這個底層的架構是Adeos 是另一個open source的project
在api呼叫上可以看到不同層級的抽象化
ipipe_XXX -> rthal_XXX -> xnXXX
負責傳送interrupt的程式稱為ipipe 示意圖 :

image

可以找到ipipe_raise_irq()將interrupt推到pipeline

在ipipe上每個domain都有自己的優先度 高優先度的domain會先接收到interrupt 高優先度的domain的thread 可以preempt低優先度domain的thread

Xenomai 3

xenomai3有兩種configuration:

  • Cobalt: 採用dual kernel架構,是xenomai 2的延伸

  • Mercury: 使用單kernel形式,在linux kernel上提供xenomai api,由於本身依賴linux,一般來說會以PREEMPT_RT提供real-time services

Xenomai 3 dual kernal configuration : Cobalt

image
多一個 priority 比 linux 還高叫 cobalt 的 core 去處理 real-time 的事情,提供不同的 real-time API 給不同的 applications 使用。並且利用Optimistic interrupt protection 機制減少 changing the interrupt mask,一般的機制在每次進入critical section時都要interrupt mask,而Optimistic interrupt protection可以不用。而real-time 在意的 “deadline”,實際上就是探討 latency (latency 越大,系統越難在時限內完成完成高優先權任務,自然即時能力就越差),而 latency 很大的來源則是 interrupt handling。

具有實時內核cobalt、實時驅動模型RTDM、實時應用POSIX接口庫libcobalt,然後再基於libcobalt實現的其他API skins,如Alchemy API、VxWorks® emulator、pSOS® emulator等(具體查看應用編程接口文檔https://xenomai.org/documentation/xenomai-3/html/xeno3prm),即VxWorks、pSOS應用程序可稍微修改源碼就可以在xenomai上編譯運行。
需要說明的是Alchemy API是xenomai除posix外的官方編程接口,提供了更接近於傳統RTOS編程方式的編程接口,對於不熟悉linux應用開發的MCU開發人員也能很快上手。在xenomai2上Alchemy API是xenomai的原生編程接口,性能最好,posix API是在Alchemy API上實現的skin。在xenomai3相反,Alchemy API、VxWorks、pSOS均基於posix接口實現,也正因爲這樣誕生了mercury方式。

Xenomai 3 single kernel configuration :Mercury

image

運用本機的 linux core 在 PREEMPT_RT之上達到 real-time 的事情,這裡不是強制的,看 applications 對反應時間和 maximum jitter 的要求,有些甚至會作到某種程度 deadline 的忽略。

基於直接修改linux內核源代碼的PREEMPT RT,應用空間在glibc之上,添加xenomai API庫,如下圖所示。可以在不支持cobalt內核時,可使用該方法運行xenomai應用;也就是說你還可以通過mercury方式在PREEMPT RT上編譯運行VxWorks、pSOS等接口的應用程序。 當然,也可不需要PREEMPT RT,直接使用linux,只是實時性就……

xenomai3-cobalt 結構

image
image
在內核空間,在標準linux基礎上添加一個實時內核Cobalt,得益於基於ADEOS(Adaptive Domain Environment for Operating System),使Cobalt在內核空間與linux內核並存,並把標準的Linux內核作爲實時內核中的一個idle進程在實時內核上調度。

2000年,Karim發表了一篇名爲《操作系統的自適應域環境》的論文(即Adeos,Adaptive Domain Environment of Operating System),該論文描述了一種簡單而智能的方案,用於在同一系統上運行的多個內核之間共享公共硬件資源。他通過“pipeline”抽象來說明在x86硬件上共享中斷的基本機制,根據整個系統給定的優先級,依次向每個內核傳入中斷。他倡導一種對硬件中斷進行優先級排序的新方法,以便可以開發基於Linux內核的實時擴展,而無需使用當時已被某些專有RTOS供應商申請授予專利方法(這裏的RTOS供應商和專利指的就是WindRiver和RTlinux使用的RTHAL技術)。 ADEOS (Adaptive Domain Environment for Operating System),提供了一個靈活的環境,可以在多個操作系統之間或單個OS的多個實例之間共享硬件資源,從而使多個優先級域可以同時存在於同一硬件上。早期在xenomai 2上使用。 2005年6月17日,Philippe Gerum發佈用於Linux內核的I-pipe,I-pipe基於ADEOS,但是I-pipe更精簡,並且只處理中斷,xenomai3使用I-pipe。

ADEOS ,其核心思想是Domain,也就是範圍的意思,linux內核有linux內核的範圍,cobalt內核有cobalt內核的範圍。

  • 兩個內核管理各自範圍內的應用、驅動、中斷;
  • 兩個domain之間有優先級之分,cobalt內核優先級高於linux內核;
  • I-pipe優先處理高優先級域的中斷,來保證高優先級域的實時性。
  • 高優先級域可以通過I-pipe 向低優先級域發送各類事件等。

image

在用戶空間,添加針對實時應用優化的庫--libcobalt,libcobalt提供POSIX接口給應用空間實時任務使用,應用通過libcobalt讓實時內核cobalt提供服務。
驅動方面,xenomai提供實時驅動框架模型RTDM(Real-Time Driver Model),專門用於Cobalt內核,基於RTDM進行實時設備驅動開發,爲實時應用提供實時驅動。RTDM將驅動分爲2類:

  • 字符設備(open/close, read, write, ioctl),如UART,UDD,SPI……
  • 協議設備(socket, bind, send, recv, etc),如UDP/TCP,CAN,IPC,……

中斷方面,I-Pipe(interrupt Pipeline)分發Linux和Xenomai之間的中斷,並以Domain優先級順序傳遞中斷。I-Pipe傳遞中斷如下圖所示,對於實時內核註冊的中斷,中斷產生後能夠直接得到處理,保證實時性。對於linux的中斷,先將中斷記錄在i-log,等實時任務讓出CPU後,linux得到運行,該中斷纔得到處理。

image

實時內核cobalt與非實時內核linux相結合,既能提供工業級RTOS的硬實時性能,又能利用linux操作系統非常出色的生態、網絡和圖形界面服務,在產品的開發週期和成本控制方面都有巨大優勢 。

系統基本實現深度解析參考

xenomai內核解析--雙核系統調用(一)
xenomai內核解析--任務同步互斥機制(一)--優先級倒置
xenomai內核解析--實時內存管理--xnheap
xenomai內核解析--信號signal(一)---Linux信號機制

xenomai proc文件信息介紹

1.1 實時外設中斷信息

ipipe
ipipe爲了xenomai與linux之間更好地結合,引入了虛擬中斷。虛擬中斷和常規softirq本質上不同,softirq只存在linux中,ipipe虛擬中斷更近似於硬件中斷,但不是硬件觸發,由內核之間需要處理緊急任務時向另一個內核發送,ipipe處理虛擬中斷與處理硬件中斷流程一致,這些中斷信息分爲Llinux和xenomai,分別對應文件/proc/ipipe/Linux和/proc/ipipe/Xenomai。

dovetail

dovetail區別與ipipe,它是在已有linux中斷管理代碼上進行擴展,爲實時核提供與ipipe相同的功能。所以/proc/interrupts就包含了ipipe層和xenomai實時中斷信息。

1.2 查看實時核信息

xenomai內核相關信息均爲位於/proc/xenomai/目錄下:
image

xenomai調度cpu
ubuntu@work-host:/proc/xenomai$ cat /proc/xenomai/affinity
000000ff

/proc/xenomai/affinity 中是一組掩碼,每一個bit表示系統中的一個CPU,該源碼錶示cobalt內核管理的CPU集,若實時應用程序中沒有設置affinity,那麼該實時會調度在該掩碼下的任意一個CPU上。當我們需要將指定cpu給cobalt調度的時候,可以通過添加內核參數 xenomai.supported_cpus=0x06 來修改,這通常結合linux參數isolcpus來優化實時性能。

硬件timer與延遲信息

/proc/xenomai/clock/coreclk包含了系統的硬件timer和gravity信息。

root@xxxxx:/proc/xenomai# cat clock/coreclk
gravity: irq=1880 kernel=6880 user=6880
 devices: timer=timer2, clock=ipipe_tsc
watchdog: off
   setup: 1880
  ticks: 230615579053 (0035 b1c279ad)
  • gravity在前文autotune工具部分已經解釋,它的值可通過autotune 命令來重新測量調整:
    root@xxxxx:/proc/xenomai# autotune
    == auto-tuning started, period=1000000 ns (may take a while)
    irq gravity... 2880 ns
    kernel gravity... 4320 ns
    user gravity... 7200 ns
    == auto-tuning completed after 38s
    root@xxxxx:/proc/xenomai# cat clock/coreclk
    gravity: irq=2880 kernel=4320 user=7200
     devices: timer=timer2, clock=ipipe_tsc
    watchdog: off
       setup: 1880
      ticks: 25641430824 (0005 f8592f28)
    
  • 如果latency測試後只修user gravity, echo xxxx > /proc/xenomai/latency即可:
    root@xxxxx:/proc/xenomai# echo 6680 > latency
    root@xxxxx:/proc/xenomai# cat clock/coreclk
    gravity: irq=2880 kernel=4320 user=6680
     devices: timer=timer2, clock=ipipe_tsc
    watchdog: off
       setup: 1880
      ticks: 28659743127 (0006 ac40f997)
    
  • 若三者都需要修改,可通過 echo irq=xxxx kernel=xxxx user=xxxx> /proc/xenomai/clock/coreclk 修改:
    root@xxxxx:/proc/xenomai# echo irq=0 kernel=0 user=0 > clock/coreclk
    root@xxxxx:/proc/xenomai# cat clock/coreclk
    gravity: irq=0 kernel=0 user=0
     devices: timer=timer2, clock=ipipe_tsc
    watchdog: off
       setup: 1880
      ticks: 32430637968 (0007 8d044390)
    
faults

文件/proc/xenomai/faults提供了cobalt內核實時上下文產生的fault統計信息,爲什麼需要關注CPU fault?回到實時性,如果我們的實時任務真正進行關鍵的行爲,此時產生了異常,異常必須解決才能繼續運行,這就導致了結果輸出的不確定性,即影響實時性。這也是爲什麼我們在xenomai應用編程時不能通過glibc庫進行動態內存分配的原因,因爲linux內存的惰性內存分配機制,只有在應用訪問分配的虛擬內存地址時才產生缺頁異常(Page fault)進行物理內存分配,同時linux在內存水位過低時也會進行內存回收,需要考慮。這也是爲什麼VxWorks等RTOS很少使用MMU的原因。

該文件只統計cobalt內核管理的CPU且在實時調度上下產生的異常,因此,若你運行的實時任務抖動比較大,建議查看一下文件,是否是受到異常的影響。

X86下各類異常如下:

ubuntu@work-host:/proc/xenomai$ cat faults
TRAP         CPU0        CPU1
  0:            0           0    (Divide error)
  1:            0           0    (Debug)
  3:            0           0    (Int3)
  4:            0           0    (Overflow)
  5:            0           0    (Bounds)
  6:            0           0    (Invalid opcode)
  7:            0           0    (FPU not available)
  8:            0           0    (Double fault)
  9:            0           0    (FPU segment overrun)
 10:            0           0    (Invalid TSS)
 11:            0           0    (Segment not present)
 12:            0           0    (Stack segment)
 13:            0           0    (General protection)
 14:            0           0    (Page fault)
 15:            0           0    (Spurious interrupt)
 16:            0           0    (FPU error)
 17:            0           0    (Alignment check)
 18:            0           0    (Machine check)
 19:            0           0    (SIMD error)
heap
ubuntu@work-host:/proc/xenomai$ cat heap
    TOTAL      FREE  NAME
  4194304   4192256  system heap
   262144    262016  shared heap

該文件顯示了xenomai heap的信息。前面說到,爲避免實時性受到影響,實時應用運行過程中不能使用linux的惰性內存分配接口,在內核裏也是一樣,一是linux內核內存分配算法的不確定性,二是linux內核惰性分配原則。所以xenomai的解決機制是,xenomai內核初始化時預先分配一大片內存,並一一讀寫訪問來建立虛擬內存與物理內存的映射,再通過自己的內存分配算法進行管理,該分配算法時間是確定的,xenomai自己管理的內存稱爲xnheap,xenomai運行過程中的動態內存分配均從xnheap中分配,爲避免多個子系統同時訪問一個xnheap,xenomai內核內有多個heap,這些heap的大小可通過內核參數 xenomai.sysheap_size=<kbytes> 配置,或內核編譯時配置:

[*] Xenomai/cobalt  ---> 
     Sizes and static limits  --->
          (512) Number of registry slots                                   
          (4096) Size of system heap (Kb) 
          (512) Size of private heap (Kb) 
          (512) Size of shared heap (Kb)

關於 xnheap 內存分配管理算法,有單獨的文章介紹。

registry

什麼是registry?與內存資源類似,在操作系統管理應用程序或爲應用程序提供服務的實時,需要管理很多對象。

舉個例子,有兩個xenoami實時任務, 它們使用semaphore做同步互斥,任務1創建一個名爲/test-sem的semaphore,任務2打開這個semaphore並使用該semaphore,思考下面兩個問題:

  • 問題1:任務1創建的這個semaphore是如何管理的?
  • 問題2:任務2又是如何通過name找到它的?

這裏例子中的semaphore在操作系統內核中可以一種內核對象,registry提供了一個機制,用於保存xenomai全局內核對象。這些對象分爲兩種,一種有name,常用於兩個及以上進程間,可以通過name來找到同一對象。另一種沒有name,常用於同一進程空間。

registry的大小和heap一樣預先分配,xenomai運行過程中直接獲取,一是全局方便查找降低實現複雜度,二避免內存分配導致系統heap競爭。默認大小爲512個條目。

ubuntu@work-host:/proc/xenomai$ cat registry/usage
10/512

若你運行在xenomai上的軟件比較龐大和複雜,512個不夠使用,可重新配置編譯內核:

-> Xenomai/cobalt (XENOMAI [=y]) 
	-> Sizes and static limits 
	(512) Number of registry slots

關於registry內核對象的管理機制,會有單獨的文章介紹。

1.3 調度與任務狀態

下面看最重要的部分,xenomai內核和實時任務運行狀態信息在/proc/xenomai/sched下:

image

其中/proc/xenomai/sched/rt/threads/proc/xenomai/sched/threads,前者僅包括優先級大於0的xenomai任務信息,後者包括所有xenomai調度的任務信息,比如我們在運行latency時,只有sampling線程是有優先級的,主線程和display線程優先級均爲0。

線程狀態
root@xxxxx:/proc/xenomai/sched# cat threads
CPU  PID    CLASS  TYPE      PRI   TIMEOUT       STAT       NAME
  0  0      idle   core       -1   -             R          [ROOT]
  0  265    rt     core       98   -             W          [rtnet-stack]
  0  266    rt     core        0   -             W          [rtnet-rtpc]
  0  281    rt     core        0   -             W          [rtnetproxy]
  0  380    rt     cobalt      0   -             X          latency
  0  382    rt     cobalt      0   -             W          display-380
  0  383    rt     cobalt     99   -             Wt         sampling-380
root@xxxxx:/proc/xenomai/sched# cat rt/threads
CPU  PID    PRI      PERIOD     NAME
  0  265     98      -          rtnet-stack
  0  383     99      -          sampling-380
  • CPU 表示該實時任務在哪個CPU的調度隊列上。
  • CLASS 表示該任務的調度類
  • TYPE 中core表示該任務是內核態任務,cobalt用戶態任務
  • PRI 表示任務優先級
  • STAT 表示任務所處狀態
系統統計信息

下面看cobalt內核統計信息/proc/xenomai/sched/stat,這對我們查找實時問題時有幫助,以latency運行爲例,輸出如下:

root@xxxxx:/proc/xenomai/sched# cat stat
CPU  PID    MSW        CSW        XSC        PF    STAT       %CPU  NAME
  0  0      0          40051      0          0     00018000   99.1  [ROOT]
  0  265    0          2          0          0     00000042    0.0  [rtnet-stack]
  0  266    0          2          0          0     00020042    0.0  [rtnet-rtpc]
  0  282    0          2          0          0     00020042    0.0  [rtnetproxy]
  0  329    1          1          5          0     000600c0    0.0  latency
  0  331    40         80         44         0     00060042    0.0  display-329
  0  332    2          40003      40046      0     0004c042    0.6  sampling-329
  0  0      0          44791      0          0     00000000    0.3  [IRQ16: [timer]]
  0  0      0          0          0          0     00000000    0.0  [IRQ46: 4a100000.ethernet]
  0  0      0          0          0          0     00000000    0.0  [IRQ47: 4a100000.ethernet]

它統計了cobalt內核線程、用戶態線程、中斷的信息,這些信息包括:

  • CPU 運行的CPU和PID
  • MSW 域上下文切換。xenomai是雙內核結構,xenomai應用可以無縫使用linux提供的服務,但這是有風險的,因爲使用linux服務需要切換到linux非實時調度上下文,無法保證任務的實時性。MSW表示的就是實時域與非實時域之間的切換次數。

latency是主線程,它創建完高優先級線程sampling-329和負責結果打印的低優先級線程display-329後,等待SIGTERM等結束信號。間隔執行cat stat發現display-329的MSW會不斷增大,是因爲打印輸出需要使用linux提供的服務進行終端打印;而高優先級sampling-329的MSW沒有變化,因爲該線程創建後,沒有調用任何linux服務全程在實時內核上下文運行。爲什麼sampling-329 MSW爲2? 因爲xenomai實時線程的創建是通過linux來完成 的。

image

因此,如果你的實時任務會出現大的抖動,那麼請通過該文件觀察,是否因爲不經意調用了linux的服務,切換到linux域引起的。

  • CSW xenomai內核上下文切換次數。
  • XSW 切換到linux域後,由linux內核調度的上下文切換次數。
  • PF 爲Page fault產生次數。
  • STAT 運行狀態掩碼
  • %CPU CPU使用率,需要額外說明的是,[ROOT]表示的是cobalt內核調度下的linux,雙核下linux已經退化爲cobalt內核調度的一個任務。

Xenomai編程注意事項

Reference

https://www.cnblogs.com/wsg1100/category/1744176.html
SourceCode
http://wiki.csie.ncku.edu.tw/embedded/xenomai
https://blog.csdn.net/pupil_wjj/article/details/119456869
https://zhuanlan.zhihu.com/p/520467236
https://blog.csdn.net/tjcwt2011/article/details/81200111

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章