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

下載本文檔

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

文檔簡(jiǎn)介

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

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

3、空間任務(wù)。 此文檔僅介紹在用戶空間執(zhí)行的實(shí)時(shí)性任務(wù),而要使用這兩個(gè)調(diào)度器,需將rtai_hal.ko,rtai_sched.ko,rtai_lxrt.ko三個(gè)模塊加載進(jìn)Linux內(nèi)核,因?yàn)橹挥袑⑦@些模塊加載進(jìn)內(nèi)核才能使這兩個(gè)調(diào)度器運(yùn)行起來(lái)并且能為實(shí)時(shí)性進(jìn)程線程提供調(diào)度效勞。也即在用戶空間編寫(xiě)的實(shí)時(shí)性進(jìn)程任務(wù)需要上述兩個(gè)調(diào)度器中的一個(gè)提供調(diào)度效勞才能正常運(yùn)行?,F(xiàn)在開(kāi)場(chǎng)吧! 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) /信號(hào)處理函數(shù)end=0; /使靜態(tài)變量為0,這將是主函數(shù)的死循環(huán)被breakintmain(void)RT_TASK*task=0; /定義實(shí)時(shí)任務(wù)指針,用于指向被創(chuàng)立的實(shí)時(shí)性任務(wù)intperiod=0; /定義周期變量,用于存儲(chǔ)定時(shí)器的周期signal(SIGKILL,endHandler); /連接幾個(gè)主要關(guān)閉信號(hào)的信號(hào)處理函數(shù)signal(SIGTERM,endHandler); /包括KILL 也即殺死進(jìn)程信號(hào),TERM關(guān)閉信號(hào)signal(SIGALRM,endHandler); /這些信號(hào)被

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

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

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

8、ete(task); /刪除實(shí)時(shí)性任務(wù),此時(shí)控制權(quán)將交回Linuxprintf("End of the Application!n");return0; /返回0值 2、建立Makefile文件在Makefile文件內(nèi)如下所寫(xiě):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注釋?zhuān)?CFLAGS宏用于設(shè)置編譯選項(xiàng),可以看到“-I/usr/realtime/include這項(xiàng),此項(xiàng)用于設(shè)置包含rtai_lxrt.h的路徑path,其原因在于此路徑不是Linux的標(biāo)準(zhǔn)頭文件路徑,因此需要手動(dòng)在編譯選項(xiàng)里指定其路徑,其選項(xiàng)為“-I?!?o選項(xiàng)用于告訴編譯器編譯成可執(zhí)行文件。 DFLAGS宏用于設(shè)置連接選項(xiàng),可以看到“-L/usr/realtime/lib這項(xiàng),這項(xiàng)用于指定靜態(tài)庫(kù)“l(fā)iblxrt.a的路徑,因?yàn)榇宋募辉贚inux的標(biāo)準(zhǔn)庫(kù)路徑下,需要手動(dòng)設(shè)置其路徑,其選項(xiàng)為“-L。需要手動(dòng)指定其靜態(tài)庫(kù),可見(jiàn)“-llxrt “-lpthread兩項(xiàng),其中“-llxrt實(shí)

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

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

12、config即為設(shè)置靜態(tài)庫(kù)查找路徑命令,其參數(shù)即為你需要設(shè)置的靜態(tài)庫(kù)路徑。 此時(shí),你再執(zhí)行: ./main 你又發(fā)現(xiàn)出問(wèn)題了,其表現(xiàn)為控制臺(tái)返回“segmentation fault,也即為段錯(cuò)誤。還記得在“RTAI Linux 調(diào)度器一節(jié)中曾提到過(guò)rtai_hal.ko, rtai_sched.ko, rtai_lxrt.ko三個(gè)模塊,根據(jù)該小節(jié)中的解釋?zhuān)枰\(yùn)行main程序,必須要將這三個(gè)模塊加載到內(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 此時(shí),再重新執(zhí)行以下命令: ./main 此時(shí),控制臺(tái)上將會(huì)不斷打印“Hello World!。 此時(shí)可以通過(guò)按下“Ctrl + C來(lái)終止程序,而更建議在任務(wù)管理器下將此進(jìn)程殺死,因?yàn)槌绦蚶飳?shí)現(xiàn)了信號(hào)kill的處理函數(shù)。疑惑還是存在 疑惑的存在主要是在main函數(shù)里的各個(gè)步驟還是難以讓人理解。例如singal函數(shù)的調(diào)用是一件比較難以明白的處理,里面連接了kill信號(hào),在kill的處理句柄里可以看到它將end賦0,而end為0將會(huì)導(dǎo)致main函數(shù)里的循環(huán)完畢。而在Linux系統(tǒng)里kil

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

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

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

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

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

19、給0,將會(huì)使用默認(rèn)的512單位未知。 第四個(gè)參數(shù)為任務(wù)的消息緩沖大小,如果為0,那么默認(rèn)大小為256單位未知。 第五個(gè)參數(shù)為L(zhǎng)inux任務(wù)的優(yōu)先級(jí)設(shè)置。下文會(huì)有解釋 第六個(gè)參數(shù)為處理器掩碼,類(lèi)如為0x01時(shí)選用處理器0,為0x02時(shí)選用處理器1,為0x03時(shí)為處理器0和1。 rt_task_init_schmod函數(shù)實(shí)際可以使用以下過(guò)程分解: 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); /注冊(cè)和初始化本進(jìn)程為軟實(shí)時(shí)任務(wù) sched_param為一個(gè)調(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為L(zhǎng)inux的經(jīng)典調(diào)度算法實(shí)現(xiàn)的,而SCHED_FIFO為一種軟實(shí)時(shí)調(diào)度機(jī)制,它的優(yōu)先級(jí)有從199,而SCHED_OTHER代表的是0,數(shù)值越大,那么優(yōu)先級(jí)越大。在SCHED_FIFO調(diào)

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

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論