編寫LXRT(RTAI-LXRT)用戶空間程序_第1頁
編寫LXRT(RTAI-LXRT)用戶空間程序_第2頁
編寫LXRT(RTAI-LXRT)用戶空間程序_第3頁
編寫LXRT(RTAI-LXRT)用戶空間程序_第4頁
編寫LXRT(RTAI-LXRT)用戶空間程序_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、. .編寫LXRTRTAILXRT用戶空間程序Asad Chan 2021-06-28 此文檔僅為那些剛涉獵RTAI Linux的愛好者編寫。在用戶空間下編寫RTAILXRT程序并不是一件困難的事,可以參考"DIAPM RTAI Programming Guide 1.0"和"How to port your C+ GNU/Linux application to RTAI/LXRT"。而這兩個文檔卻沒有一個完整在用戶空間能執(zhí)行的例子,所以往往會造成看了遇到問題不知問題出在哪里。往往有的程序編寫好了,也編譯好了,在控制臺下執(zhí)行卻出現(xiàn)了segmentati

2、on fault字樣。RTAI Linux 調(diào)度器請參考RTAI 3.3 User Manual rev0.2 RTAI分別在內(nèi)核空間和用戶空間提供了兩個對等的任務(wù)調(diào)度器,一個為rtai_sched,一個為rtai_lxrt,這兩個調(diào)度器主要是他們所能調(diào)度的可調(diào)度任務(wù)有所差異,而這兩個調(diào)度器都能調(diào)度用戶空間和內(nèi)核空間的任務(wù)。rtai_sched能調(diào)度Linux下的各種任務(wù),例如process,thread,kthread,而同時它還能調(diào)度RTAI 內(nèi)核空間任務(wù)請區(qū)分Linux內(nèi)核和 RTAI 內(nèi)核。而rtai_lxrt僅能調(diào)度process,thread,kthread,卻不能調(diào)度RTAI內(nèi)核

3、空間任務(wù)。 此文檔僅介紹在用戶空間執(zhí)行的實時性任務(wù),而要使用這兩個調(diào)度器,需將rtai_hal.ko,rtai_sched.ko,rtai_lxrt.ko三個模塊加載進(jìn)Linux內(nèi)核,因為只有將這些模塊加載進(jìn)內(nèi)核才能使這兩個調(diào)度器運行起來并且能為實時性進(jìn)程線程提供調(diào)度效勞。也即在用戶空間編寫的實時性進(jìn)程任務(wù)需要上述兩個調(diào)度器中的一個提供調(diào)度效勞才能正常運行?,F(xiàn)在開場吧! 1、建立main.c文件內(nèi)容如下:#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<rtai_lxrt.h&g

4、t;staticintend=1;voidendHandler(intsig) /信號處理函數(shù)end=0; /使靜態(tài)變量為0,這將是主函數(shù)的死循環(huán)被breakintmain(void)RT_TASK*task=0; /定義實時任務(wù)指針,用于指向被創(chuàng)立的實時性任務(wù)intperiod=0; /定義周期變量,用于存儲定時器的周期signal(SIGKILL,endHandler); /連接幾個主要關(guān)閉信號的信號處理函數(shù)signal(SIGTERM,endHandler); /包括KILL 也即殺死進(jìn)程信號,TERM關(guān)閉信號signal(SIGALRM,endHandler); /這些信號被

5、收到時將會break主程序的循環(huán)if(!(task=rt_task_init_schmod(nam2num("TEST"),0,0,0,SCHED_FIFO,0x0f) /初始化本進(jìn)程 /為實時性任務(wù)printf("Can't initial the taskn");exit(1);mlockall(MCL_CURRENT|MCL_FUTURE); /鎖定本進(jìn)程內(nèi)存,防止本進(jìn)程的內(nèi)存頁被換出 /導(dǎo)致的實時性被破壞period=start_rt_timer(nano2count(10000); /啟動定時器,設(shè)置其定時周期/頻率, /根據(jù)定時器是否

6、是oneshotrt_make_hard_real_time(); /使本任務(wù)為硬hard實時性任務(wù)rt_task_make_periodic(task,rt_get_time()+period*10,period*100); /設(shè)置本任務(wù)的周期while(end) /如果end為1那么一直執(zhí)行,end0,那么說明接收到了kill/term/alrm三個信號 /中的一個,證明此進(jìn)程被用戶終止或alrm,那么break此循環(huán),完畢此任務(wù)printf("Hello World!n"); /打印字符,注意,此為syscall,會導(dǎo)致任務(wù)進(jìn)入非實時性 /狀態(tài),當(dāng)此調(diào)用完畢時將會重新

7、返回到實時性狀態(tài) /* 在實際應(yīng)用中如果你的任務(wù)是周期性執(zhí)行的,請在此處填寫需要執(zhí)行的周期性過程。 如果你的任務(wù)是需要等待某個事件、者信號量或者某個消息的到來,請你建立相應(yīng) 的事件、信號量、消息,并在此處等待相應(yīng)的量,相應(yīng)的量到來時執(zhí)行你需要的 操作。 */rt_task_wait_period(); /使當(dāng)前任務(wù)進(jìn)入休眠,知道下一次執(zhí)行周期到達(dá)被喚醒, /如果execution time >= deadline那么此函數(shù)不會使 /任務(wù)進(jìn)入休眠狀態(tài)rt_make_soft_real_time(); /是任務(wù)進(jìn)入軟實時狀態(tài)stop_rt_timer(); /停頓定時器rt_task_del

8、ete(task); /刪除實時性任務(wù),此時控制權(quán)將交回Linuxprintf("End of the Application!n");return0; /返回0值 2、建立Makefile文件在Makefile文件內(nèi)如下所寫:CC = gccCFLAGS = -I/usr/realtime/include -oDFLAGS = -L/usr/realtime/lib -llxrt -lpthreadTARGET = mainSOURCE = main.call:$(CC) $(SOURCE) $(CFLAGS) $(TARGET) $(DFLAGS)clean:rm ma

9、in注釋: CFLAGS宏用于設(shè)置編譯選項,可以看到“-I/usr/realtime/include這項,此項用于設(shè)置包含rtai_lxrt.h的路徑path,其原因在于此路徑不是Linux的標(biāo)準(zhǔn)頭文件路徑,因此需要手動在編譯選項里指定其路徑,其選項為“-I?!?o選項用于告訴編譯器編譯成可執(zhí)行文件。 DFLAGS宏用于設(shè)置連接選項,可以看到“-L/usr/realtime/lib這項,這項用于指定靜態(tài)庫“l(fā)iblxrt.a的路徑,因為此文件不在Linux的標(biāo)準(zhǔn)庫路徑下,需要手動設(shè)置其路徑,其選項為“-L。需要手動指定其靜態(tài)庫,可見“-llxrt “-lpthread兩項,其中“-llxrt實

10、為liblxrt.a的縮寫,此實為GNU連接器的使用規(guī)那么,由此可知“-lpthread即為libpthread.a的縮寫。 “$()符號用于對定義的宏進(jìn)展解析,例如“$(CC)在上面的例子中等價為“gcc,“$(SOURCE)等價為“main.c,其他各項亦按此種形式解析。 3、編譯main.c文件 假設(shè)你的main.c、Makefile兩個文件放在絕對路徑/usr/root/workspace/main目錄里,那么在控制臺下進(jìn)入到此目錄,執(zhí)行以下命令即可: make 注:“為回車的意思。 此時控制臺上會顯示“gcc main.c -I/usr/realtime/include -o mai

11、n -L/usr/realtime/lib -llxrt -lpthread,同時在main目錄下會生成可執(zhí)行文件main。 4、執(zhí)行main 此時,在上面步驟下在控制臺下執(zhí)行以下命令: ./main 此時,會返回一個錯誤,類似于“can't open file liblxrt.so.1 .之類的字樣,其原因是文件liblxrt.so.1并不是在Linux系統(tǒng)設(shè)定的靜態(tài)庫路徑下,那么要解決這個問題需要將在第2步中設(shè)定路徑“/usr/realtime/lib參加到Linux系統(tǒng)能尋找的靜態(tài)庫的路徑中,此可以通過以下命令設(shè)定: ldconfig /usr/realtime/lib 注:ld

12、config即為設(shè)置靜態(tài)庫查找路徑命令,其參數(shù)即為你需要設(shè)置的靜態(tài)庫路徑。 此時,你再執(zhí)行: ./main 你又發(fā)現(xiàn)出問題了,其表現(xiàn)為控制臺返回“segmentation fault,也即為段錯誤。還記得在“RTAI Linux 調(diào)度器一節(jié)中曾提到過rtai_hal.ko, rtai_sched.ko, rtai_lxrt.ko三個模塊,根據(jù)該小節(jié)中的解釋,需要運行main程序,必須要將這三個模塊加載到內(nèi)核空間,以使其提供調(diào)度任務(wù)效勞功能。首先要切換到目錄/usr/realtime/modules下,也即如下命令: cd /usr/realtime/modules 繼續(xù)執(zhí)行以下命令: insm

13、od rtai_hal.ko insmod rtai_sched.ko insmod rtai_lxrt.ko 此時,再重新執(zhí)行以下命令: ./main 此時,控制臺上將會不斷打印“Hello World!。 此時可以通過按下“Ctrl + C來終止程序,而更建議在任務(wù)管理器下將此進(jìn)程殺死,因為程序里實現(xiàn)了信號kill的處理函數(shù)。疑惑還是存在 疑惑的存在主要是在main函數(shù)里的各個步驟還是難以讓人理解。例如singal函數(shù)的調(diào)用是一件比較難以明白的處理,里面連接了kill信號,在kill的處理句柄里可以看到它將end賦0,而end為0將會導(dǎo)致main函數(shù)里的循環(huán)完畢。而在Linux系統(tǒng)里kil

14、l信號是有默認(rèn)的處理句柄的,那么我們?yōu)槭裁床挥盟哪J(rèn)處理句柄呢?它同樣可以使應(yīng)用程序退出并釋放相應(yīng)的內(nèi)存。 1、頭文件 首先,既然在用戶空間編寫RTAI-LXRT可運行程序,那么意味著并且實際上是可以調(diào)用Linux的系統(tǒng)調(diào)用,標(biāo)準(zhǔn)庫等用戶空間能運行的函數(shù),那么可以包含stdio.h, stdlib.h,這兩個標(biāo)準(zhǔn)頭文件,以使程序能調(diào)用標(biāo)準(zhǔn)的庫函數(shù),同時需要包含signal.h頭文件,此頭文件主要是提供signal連接關(guān)閉程序句柄,而需要使用RTAILXRT提供的實時性功能,那么毫無疑問需要包含rtai_lxrt.h,請記得rtai_lxrt.h在/usr/realtime/include假設(shè)

15、是按照RTAI安裝的默認(rèn)路徑目錄里,因此需要在編譯選項里指定這一路徑,否那么將不能找到此頭文件。頭文件包含如下所示:#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <rtai_lxrt.h>2、RT_TASK指針 可以看到在程序的開頭聲明了指針task,可以知道它為RT_TASK構(gòu)造體指針,此構(gòu)造體指針用于指向需要設(shè)置為實時性的任務(wù),需要這個指針的原因是當(dāng)在程序中將一個process本文檔例子中即為main Process/pthread/kthread向RTAI內(nèi)

16、核注冊后,task將指向此prcess/pthread/kthread,在隨后的過程中還需要設(shè)置task指向的任務(wù)的一些屬性,比方該任務(wù)的周期等屬性,那么需要使用task作為設(shè)置該任務(wù)設(shè)置的口,并且在程序完畢時還要通過它來從RTAI內(nèi)核中刪除任務(wù)。請詳細(xì)閱讀代碼。 3、signal函數(shù) 在關(guān)閉一個進(jìn)程時,進(jìn)程將會收到kill信號,在Linux系統(tǒng)里,在收到kill信號后,默認(rèn)的kill句柄將會執(zhí)行從Linux內(nèi)核中刪除任務(wù)的操作,這個操作包括關(guān)閉收到該信號的進(jìn)程所翻開的所有文件,釋放該進(jìn)程所占的內(nèi)存頁,將該進(jìn)程的PCB從Linux內(nèi)核中刪除等操作,最終導(dǎo)致該進(jìn)程的完畢。 根據(jù)上述,可以知道,當(dāng)

17、本文所寫的main函數(shù)的while循環(huán)沒有被break,而收到的kill信號,也即是用戶關(guān)閉該進(jìn)程,而同時沒有連接上述所寫的endHandler句柄,那么將會直接執(zhí)行Linux的默認(rèn)kill信號句柄,此時將導(dǎo)致程序在while循環(huán)里被完畢,而沒有執(zhí)行到while循環(huán)以下的過程,比方rt_make_soft_real_time(),stop_rt_timer(),rt_task_delete(task),而最終會導(dǎo)致這個已經(jīng)在RTAI內(nèi)核注冊過的任務(wù)沒有從里面刪除,而同時它已經(jīng)不存在了。 基于上述原因,需要重新kill,term等信號的處理句柄,而不使程序在while過程里被關(guān)閉,使程序最終能退

18、出while,可以調(diào)用rt_task_delete(task)過程,使得任務(wù)從RTAI內(nèi)核中刪除的目的。 4、向RTAI內(nèi)核注冊main進(jìn)程可以看到main函數(shù)里的task=rt_task_init_schmod(nam2num("TEST"),0,0,0,SCHED_FIFO,0x0f)。此過程將main進(jìn)程注冊進(jìn)RTAI內(nèi)核,并成為軟實時任務(wù)。 第一個參數(shù)為任務(wù)號,我們看到nam2num(“TEST),此調(diào)用的目的是向RTAI申請一個名為“TEST的任務(wù)號,其返回值即為該任務(wù)號。 第二個參數(shù)為該任務(wù)的優(yōu)先級,這里設(shè)置為0,即為最高優(yōu)先級。 第三個參數(shù)為任務(wù)的棧大小,如果

19、給0,將會使用默認(rèn)的512單位未知。 第四個參數(shù)為任務(wù)的消息緩沖大小,如果為0,那么默認(rèn)大小為256單位未知。 第五個參數(shù)為Linux任務(wù)的優(yōu)先級設(shè)置。下文會有解釋 第六個參數(shù)為處理器掩碼,類如為0x01時選用處理器0,為0x02時選用處理器1,為0x03時為處理器0和1。 rt_task_init_schmod函數(shù)實際可以使用以下過程分解: struct sched_param mysched; mysched.sched_priority = sched_get_priority_max(SCHED_FIFO) 1; sched_setscheduler(0,SCHED_FIFO,&

20、;mysched); rt_task_init(nam2num(“TEST),0,0,0); /注冊和初始化本進(jìn)程為軟實時任務(wù) sched_param為一個調(diào)度參數(shù)構(gòu)造體,里面有進(jìn)程的任務(wù)調(diào)度屬性字段,在這里需要修改main進(jìn)程的調(diào)度策略。在Linux系統(tǒng)里有兩種調(diào)度策略,一種是SCHED_OTHER,一種是SCHED_FIFO,一般情況下Linux用戶進(jìn)程使用的是SCHED_OTHER,SCHED_OTHER為Linux的經(jīng)典調(diào)度算法實現(xiàn)的,而SCHED_FIFO為一種軟實時調(diào)度機(jī)制,它的優(yōu)先級有從199,而SCHED_OTHER代表的是0,數(shù)值越大,那么優(yōu)先級越大。在SCHED_FIFO調(diào)

21、度策略里每一個優(yōu)先級形成一個FIFO先進(jìn)先出隊列,高優(yōu)先級的任務(wù)FIFO隊列里只要有進(jìn)程為就緒狀態(tài)將會搶占低優(yōu)先級FIFO隊列里正在運行的進(jìn)程,只有當(dāng)高優(yōu)先級FIFO隊列里的進(jìn)程都被阻塞時,低優(yōu)先級的進(jìn)程才能得到CPU執(zhí)行下去。而在每一個優(yōu)先級的隊列里,當(dāng)前進(jìn)程運行被阻塞,它將會被插入到FIFO隊列尾部,而同時如果沒有更高優(yōu)先級的任務(wù)就緒,那么將會調(diào)度本優(yōu)先級里FIFO隊列頭的進(jìn)程。 LXRT要改善Linux進(jìn)程的軟實時性,那么需要將Linux進(jìn)程轉(zhuǎn)換為SCHED_FIFO調(diào)度策略。 sched_setscheduler函數(shù)即為設(shè)置該屬性的接口。第一個參數(shù)為選擇運行的CPU,0即為選擇CPU0

22、,第二個參數(shù)為調(diào)度策略,第三個即為需要設(shè)置進(jìn)程的FIFO進(jìn)程調(diào)度策略下的優(yōu)先級。 rt_task_init即為想RTAI內(nèi)核注冊main進(jìn)程使其成為RTAI的任務(wù),其參數(shù)同rt_task_init_schmod函數(shù)的前面幾個參數(shù)一樣的含義。 “TEST任務(wù)名項主要是方便于任務(wù)之間的通信與同步。 5、鎖定main進(jìn)程所用的內(nèi)存 Linux使用了分頁管理內(nèi)存和虛擬內(nèi)存的機(jī)制,此機(jī)制即形成了Linux進(jìn)程的第二級調(diào)度,進(jìn)程的所占用的內(nèi)存隨時都會被Linux的內(nèi)存管理單元將其換出。而在實時性系統(tǒng)中,當(dāng)內(nèi)存被換出時,會使得進(jìn)程無法得到及時調(diào)度,因此將會破壞進(jìn)程的實時性,因此需要將實時進(jìn)程任務(wù)的內(nèi)存鎖定,使得其內(nèi)存在任何時候都不會被換出,而不會影響到該進(jìn)程的實時性能,如下所示: mlockall(MCL_CURRENT | MCL_FUTURE); /MCL_CURRENT 和MCL_FUTURE宏說明 /將鎖定當(dāng)前分配的內(nèi)存和以后所申請 /的內(nèi)存 6、啟動定時器 start_rt_timer(nano2count(1000),此函數(shù)啟動RT的定時器,也即實時任務(wù)的tick中斷時鐘。nano2count(1000)也即使用1000ns的周期,將其轉(zhuǎn)換為timer可以承受的數(shù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論