RTLinux下的一種實(shí)時(shí)應用通信機制
關(guān)鍵詞:RTLinux 通信接口 實(shí)時(shí) 共享內存 RT_FIFO
實(shí)時(shí)性是多任務(wù)嵌入式系統的基本特征之一,主要表現為對重要性各不相同的任務(wù)進(jìn)行統籌兼顧的合理調度能力。根據應用系統對時(shí)限要求的嚴格程度又分為軟實(shí)時(shí)和硬實(shí)時(shí)。
RTLinux作為L(cháng)inux最為通用的幾種硬實(shí)時(shí)擴展之一,表現了良好的硬實(shí)時(shí)性。同時(shí),為了更有效地為各種實(shí)時(shí)應用服務(wù),提供了多種與Linux中非實(shí)時(shí)進(jìn)行通信的接口,主要有共享內存、RT_FIFO和線(xiàn)程信號驅動(dòng)機制,三者的應用重點(diǎn)各不相同。其中前兩種較為常用[1]。由于不的實(shí)現機理,這兩種接口的應用范疇各有側重。經(jīng)過(guò)實(shí)踐,筆者認為將以上兩種接口有機地結合,利用共享內存傳送大容量、對讀/寫(xiě)時(shí)序要求不高的數據信息;同時(shí),利用RT_FIFO輔助實(shí)現對該共享內存的同步控制,能夠綜合兩者的優(yōu)勢,是RTLinux下一種十分有效的實(shí)時(shí)應用通信模式。
1 RTLinux的結構和應用程序開(kāi)發(fā)模式
作為L(cháng)inux的硬實(shí)時(shí)擴展,RTLinux一個(gè)重要的計準則在于:盡可能多地利用Linux內核所能提供的功能[2]。
顯示、記錄、設備初始化、阻塞式動(dòng)態(tài)資源分配和模塊化內核管理等無(wú)實(shí)時(shí)要求或者與硬實(shí)時(shí)性要求相悖的服務(wù)均由Linux提供。RTLinux內核則主要為實(shí)時(shí)任務(wù)提供對硬件的直接訪(fǎng)問(wèn),使得它們具有最小的延遲和最優(yōu)先的處理器利用權。
基于以上準則,RTLinux中的實(shí)時(shí)應用程序開(kāi)發(fā)通常具有一個(gè)通用的模式,如圖1所示。按照運行環(huán)境和對實(shí)時(shí)要求的嚴格程度分為實(shí)時(shí)和非實(shí)時(shí)兩個(gè)模塊。非實(shí)時(shí)模塊的功能包括結果數據顯示。用戶(hù)交互、數據存儲等;實(shí)時(shí)模塊主要負責響應數據采集外設的中斷,結果數據的采集。兩者通過(guò)RT_FIFO或者共享內存進(jìn)行通信,組成一個(gè)完整的實(shí)時(shí)數據采集程序。
2 RTLinux中的兩種通信接口
RTLinux提供了RT_FIFO和共享內存兩種標準通信接口,用于實(shí)時(shí)任務(wù)和非實(shí)時(shí)任務(wù)之間的交互。
2.1 RT_FIFO
RT_FIFO(First-In-First-Out,先進(jìn)先出)是一種提案隊列機制組織的字符設備。在Linux文件系統中,主設備號為150。一個(gè)系統平臺中能夠同加載FIFO的模塊數RTF_NO定義在rt_fifo_new.c中,一般為64,在文件系統中分別對慶設備文件/dev/rtf0..63。在系統資源允許的情況下,一個(gè)用戶(hù)進(jìn)程所能同時(shí)使用的FIFO數和每個(gè)FIFO的容量是沒(méi)限制的。
RT_FIFO具有如下特征:
*隊列中的數據傳送采用數據流形式,必須自行定義數據邊界監測機制,尤其對于不定長(cháng)度數據的傳輸。
*具備完善的同步阻塞機制,利用同一FIFO進(jìn)行通信的兩進(jìn)程間無(wú)需自行增加同步控制。
*一種點(diǎn)對點(diǎn)的通信通道,不支持單生產(chǎn)者、多消費者的使用模式。
作為一個(gè)完善的隊列模塊,RT_FIFO的使用簡(jiǎn)便易行,具體實(shí)現主要包括創(chuàng )建、讀/寫(xiě)操作、釋放三個(gè)步驟。在Linux文件系統中,RT_FIFO是一個(gè)字符設備文件,所以在非實(shí)時(shí)線(xiàn)程中訪(fǎng)問(wèn)RT_FIFO時(shí),使用標準的字符設備讀/寫(xiě)函數即可(read、write、open、close,etc)。以上函數的調用方式均為阻塞式調用:當FIFO中有數據可讀時(shí),立即返回;否則,會(huì )陷入無(wú)限等待之中。
從RT進(jìn)程中訪(fǎng)問(wèn)RT_FIFO,所涉及到的RTLAPI如下:
#includertl_fifo.h>
[創(chuàng )建]
int rtf_create(unsigned int fifo,int size);
內核空間中,為編號fifo的RT_FIFO設備分配size字節的緩沖區。fifo對應于所使用RT_FIFO的次設備號。
[釋放]
int rtf_destroy(unsigned int fifo);
釋放內核空間中次設備號為fifo的RT_FIFO設備緩沖區。
注意:以上兩個(gè)函數涉及到內核空間的緩沖區分配,必須分別在Linux的init_module()和cleanup_module()中調用,或者在用戶(hù)空間通過(guò)PSC(the user-level real-time signal library,用戶(hù)級實(shí)時(shí)庫函數)進(jìn)行調用。
[讀/寫(xiě)操作]
int rtl_get(unsigned int fifo,char *buf,int count);
從FIFO中讀出長(cháng)度為count字節的數據,存放buf之中。
Int rtf_put(unsigned int fifo,char * buf,int count);
將長(cháng)度為count字節的數據寫(xiě)入FIFO中。
Int rtf_create_handle(unsigned int fifo,int(handler)(unsigned int fifo));
創(chuàng )建一個(gè)回調函數句柄,當FIFO被Linux進(jìn)程讀/寫(xiě)時(shí),被調用。通常與rtl_get結合使用,用于異步的從Linux進(jìn)程中接收數據,從而避免采用輪詢(xún)的方式。
2.2 共享內存
共享內存是指被閑置出來(lái)專(zhuān)用于內核空間和用戶(hù)空間進(jìn)行通信的內存區域。相對于FIFO具有如下特點(diǎn):
*應用程序必須自己定義相應的協(xié)議,對于寫(xiě)入共享數據區域的有數據進(jìn)行保護,如同步控制等。
*數據可以既定格式讀/寫(xiě),各個(gè)數據域的更新十分便易。
*不是點(diǎn)對點(diǎn)的通信通道,可以支持多生產(chǎn)者、多消費者的使用模式,能夠同時(shí)被多個(gè)線(xiàn)程訪(fǎng)問(wèn)。
在RTLinux下,共享內存的使用可采用以下兩種方式:
(1)利用RTLinux中附帶的mbuff模塊
在使用mbuff之前,要求系統中已經(jīng)加載了mbuff.o模塊。該模塊中的兩個(gè)函數被分別用于分配和釋放所需的內存空間。
#includembuff.h>
[分配]
void * mbuff_alloc(const char * name,int size);
從內核空間中分配一塊與name相連,大小為size字節的內存空間,返回地址指針,設備這塊空間的引用標識為1。如與name相連的內存空間已經(jīng)存在,就僅僅返回指向該空間的地址指針,同時(shí)將其引用標識加1。
[釋放]
void mbuff_free(const char * name,int size);
將mbuff的引用標識減1。當引用標識被減為0時(shí),釋放mbuff。
注意:①mbuff_alloc使用了vmalloc函數,由于分配內核空間的需要,會(huì )交換出一系列的內核空間頁(yè)面,所以在實(shí)時(shí)線(xiàn)程、中斷處理線(xiàn)程、定時(shí)器中斷線(xiàn)程中調用這個(gè)函數是十分危險的。
②在進(jìn)程結束前,一定要調用mbuff_free函數。Mbuff所占內存空間不會(huì )因為其引用進(jìn)程的結束而自行釋放。
(2)高地址空間物理內存的直接隔離
在系統啟動(dòng)時(shí),隔離出一定大小的高地址空間物理內存,使其脫離系統運行環(huán)境,作為專(zhuān)用的共享內存區域。
圖4 共享內存互斥操作流程圖
在Linux啟動(dòng)配置文件中,插入一行以append關(guān)鍵字起始的命令行,即可實(shí)現高端內存空間的隔離。修改后的/etc/lilo.conf文件如下所示:
image=/boot/zImage
label=rtlinuxX.X
root=/dev/hda2
read_only
append=“mem=Xm”
其中,mem的值對應于被隔離空間的起始地址,可以由物理內存總容量減去所需共享空間容量得到。但是必須注意,被隔離出的共享空間的容量必須小于/usr/include/asm/param.h文件中定義的頁(yè)面長(cháng)度。Intel Pentium系列芯片的頁(yè)面長(cháng)度為4MB。
對共享內存空間的存取操作通過(guò)訪(fǎng)問(wèn)其基址來(lái)實(shí)現。必須首先定義共享內存空間的基址。
#define BASE_ADDRESS(1270x100000)
在實(shí)時(shí)和非實(shí)時(shí)模塊中有不同的基址訪(fǎng)問(wèn)方法。寫(xiě)時(shí)模塊運行于內核地址空間,可以直接將基址作為地址指針進(jìn)行存取,使用語(yǔ)句如下:
unsigned short * sharemem;
sharemem=(unsigned short *)__va(BASE_ADDRESS);
非實(shí)時(shí)模塊運行于用戶(hù)地址空間,必須先將該物理地址映射入該進(jìn)程虛擬地址空間后,才能對其進(jìn)行存取。使用命令如下:
#includeunistd.h>
#includefcntl.h>
#includesys/mman.h>
int fd;
unsigned short * sharemem;
fd=open("/dev/mem",O_RDWR); ①
sharemem=(unsigned short *)mmap(0,buflen,
PROT_READ|PROT_WRITE,
MAP_FILE|MAP_SHARED,
Fd,BASE_ADDRESS); ②
注①:訪(fǎng)問(wèn)物理內存必須打開(kāi)與其對應的設備文件/dev/mem。
注②:mmap命令的作用是將設備文件fd中,從當前進(jìn)程的虛擬地址空間,其返回值可被非實(shí)時(shí)進(jìn)程存取。
以上兩種方式在實(shí)現機理上的不同之處在于,mbuff利用vmalloc從內核地址空間分配的共享內存空間僅僅在邏輯上連續,空間的大小不受實(shí)際物理內存空間的限制;而直接隔離物理內存所獲取的緩沖區物理上連續,但是大小受到物理內存空間和當前系統狀況的限制。共同之處在于,所獲得的內存均被隔離于系統內核的運行環(huán)境之外,不會(huì )在頁(yè)面交換中被換出,所以以上兩種方法均適用于實(shí)時(shí)應用之中。
3 兩種通信接口的結合
以上兩種通信接口具有不同的適用范疇,為了實(shí)現一個(gè)完整的實(shí)時(shí)應用,通常需要將兩者結合,以一個(gè)實(shí)時(shí)數據采集程序為例,實(shí)時(shí)模塊和非實(shí)時(shí)模塊之間通常需要傳送兩種類(lèi)型的數據;結果數據和控制信息。
結果數據:由實(shí)時(shí)模塊周期性產(chǎn)生。非實(shí)時(shí)模塊用于顯示和存儲,對讀/寫(xiě)的時(shí)序性要求不高,但是通常需要由多個(gè)用戶(hù)共享,因此,利用共享內存模塊傳輸比較適合。
控制信息:主要用于實(shí)現非實(shí)時(shí)模塊和實(shí)時(shí)模塊之間的交互控制,數據量小,但是比較注重信號讀/寫(xiě)的時(shí)序性和通信過(guò)程中實(shí)時(shí)性,采用RT_FIFO實(shí)現比較適合。
圖2為通用的抽象數據流圖。
3.1 共享內存的內步控制和RT_FIFO的使用
由于對共享內存的存取通過(guò)直接訪(fǎng)問(wèn)指針來(lái)實(shí)現,操作系統不會(huì )為其提供任何同步控制,應用程序必須自行提供握手機制,來(lái)保證讀/寫(xiě)進(jìn)程之間同步。
實(shí)現同步的一種方式是接收方和發(fā)送方利用消息通信來(lái)實(shí)現握手。接收方對共享內存以輪詢(xún)的方式監測新數據的到來(lái),然后發(fā)送接收信息。為了實(shí)現握手,發(fā)送方對于每條接收消息都必須回復一個(gè)確認消息,新的接收消息只有在收到確認消息以后才能發(fā)出。
這種方式在實(shí)時(shí)模塊和非實(shí)時(shí)模塊中均須要采用輪詢(xún)的方式監測新數據和消息的到來(lái),因此會(huì )占用較多的處理器資源。所以,可以考慮利用RT_FIFO實(shí)現實(shí)時(shí)模塊和非實(shí)時(shí)模塊之間對共享內存的存取同步。利用RT_FIFO所提供的句柄功能能夠避免實(shí)時(shí)模塊對接收消息的輪詢(xún)監測,在一定程度上提高程序運行效率。
具體實(shí)現,可以通過(guò)利用RT_FIFO實(shí)時(shí)傳輸當前所寫(xiě)入或被讀出的共享內存塊序號,實(shí)現實(shí)時(shí)進(jìn)程和非實(shí)時(shí)進(jìn)程之間的步。因為RT_FIFO是一種單向傳輸隊列,為了實(shí)現交互,需要兩個(gè)傳輸方向相反的RT_FIFO,連接于兩個(gè)模塊之間,如圖3所示。
圖3中,BufNo為筆者自行定義的隊列。它的使用主要是為了避免由于RT_FIFO引起的實(shí)時(shí)部分和非實(shí)時(shí)部分之間的死鎖。
實(shí)時(shí)部分和非實(shí)時(shí)部分的各線(xiàn)程路之間對共享內存的訪(fǎng)問(wèn)為異步進(jìn)行;同時(shí),RTLinux中對RT_FIFO的進(jìn)行讀/寫(xiě)的API函數,為阻塞式操作。當FIFO0中目前沒(méi)有可讀數據時(shí),對rtf_get函數的調用會(huì )使程序陷入無(wú)限等待之中,很容易造成實(shí)時(shí)模塊和非實(shí)時(shí)模塊之間的死鎖。
為了避免這種情況,可以將BufNo作為緩沖區與FIFO0的句柄結合使用,臨時(shí)存放FIFO0中被非實(shí)時(shí)線(xiàn)程寫(xiě)入的塊序號。實(shí)時(shí)模塊不再對FIFO0進(jìn)行讀/寫(xiě),而是改由BufNo隊列中獲取當前有效的共享內存序號。如果當前無(wú)可用數據,則進(jìn)入周期等待狀態(tài)。
3.2 共享內存訪(fǎng)問(wèn)的互斥
對共享內存訪(fǎng)問(wèn)的互斥操作,包括兩個(gè)方面:實(shí)時(shí)模塊與非實(shí)時(shí)模塊之間的互斥、非實(shí)時(shí)模塊中各采集線(xiàn)程之間的互斥。
(1)實(shí)時(shí)模塊與非實(shí)時(shí)模塊之間的互斥
多線(xiàn)程之間對共享資源訪(fǎng)問(wèn)的互斥,是操作系統中一個(gè)重要的研究分支。但是在實(shí)時(shí)模塊和非實(shí)時(shí)模塊之間,問(wèn)題變得相對簡(jiǎn)單。因為,在實(shí)時(shí)進(jìn)程和非實(shí)時(shí)進(jìn)程之中,實(shí)時(shí)進(jìn)程和非實(shí)時(shí)進(jìn)程運行的環(huán)境區別很大。工作于RTLinux環(huán)境下的實(shí)時(shí)進(jìn)程具有最高的優(yōu)先級,不可能被非實(shí)時(shí)進(jìn)程中斷。所以,在實(shí)現互斥時(shí),只須保護非實(shí)時(shí)進(jìn)程對共享資源的訪(fǎng)問(wèn)即可。
抽象流程如圖4所示。利用共享內存區域的第一個(gè)字節作為訪(fǎng)問(wèn)標識,實(shí)現非實(shí)時(shí)模塊對實(shí)時(shí)模塊的互斥。
非實(shí)時(shí)進(jìn)程開(kāi)始訪(fǎng)問(wèn)共享區域時(shí),將此標識置位;訪(fǎng)問(wèn)結束時(shí),復位。實(shí)時(shí)進(jìn)程在訪(fǎng)問(wèn)共享區域前先檢測該標識,如果標識允許訪(fǎng)問(wèn),則執行寫(xiě)入操作;反之,掛起等待標識位復位,按既定周期T輪詢(xún)。
實(shí)時(shí)進(jìn)程的既定周期T的設置十分重要,周期過(guò)長(cháng),會(huì )增加發(fā)生沖突后的等時(shí)間,導致共享內存狀態(tài)改變時(shí),無(wú)法被及時(shí)寫(xiě)入;周期過(guò)短,增加了系統的輪詢(xún)次數,加重實(shí)時(shí)系統的負擔。筆者在已實(shí)現的數據采集程序中,對T的不同設置,所獲得的平均數據采集率進(jìn)行了統計,結果如圖5所示。
注:以上實(shí)驗的測試平臺為PentiumIII 667,5400轉普通硬盤(pán),RTLinux3.1、Linux kernel 2.4.4,數據流向為數據采集外設至共享內存然后存放硬盤(pán),數據的產(chǎn)生頻率為10ms。
(2)非實(shí)時(shí)模塊之間的互斥
非實(shí)時(shí)模塊中異步執行的各采集線(xiàn)程之間,可以利用互斥變量的加鎖和解鎖實(shí)現對共享內存訪(fǎng)問(wèn)的互斥。由于互斥區的執行體內,每次只允許一個(gè)線(xiàn)程進(jìn)入,為了保證程序的執行效率,在互斥區中不宜使用耗時(shí)較長(cháng)或阻塞式調用的函數。
4 結論
在RTLinux提供的實(shí)時(shí)模塊和非實(shí)時(shí)模塊之間的通信接口中,RT_FIFO和共享內存較為常用,分別適用于不同的數據類(lèi)型通信。本文提出的這種方法,能充分利用兩者的優(yōu)點(diǎn),方便地實(shí)現實(shí)時(shí)與非實(shí)時(shí)之間海量數據通信。目前已在rtLinux3.1、Linux kernel 2.4.4系統平臺上成功實(shí)現,并取得了令人滿(mǎn)意的效果。
評論