?

一種高效RTAI 共享內存管理層的研究與實現*

2013-12-23 04:47陶耀東鄭一麟
組合機床與自動化加工技術 2013年1期
關鍵詞:鏈表空閑數控系統

王 煜,林 滸,陶耀東,鄭一麟

(1.中國科學院 研究生院,北京 100049;2.中國科學院 沈陽計算技術研究所,沈陽 110168)

0 引言

隨著數控加工精度不斷提高,對數控系統軟件的可靠性要求不斷加強,這就要求必須對數控系統內部執行情況的實時監測,將數控系統內部的各種信息發送給界面實時顯示,對發現錯誤做出及時響應。

數控系統一般主要包含四個主要模塊,人機接口(HMI)、運動模塊(MOTION)、可編程邏輯模塊(PLC)和任務模塊(TASK)。HMI 運行在用戶空間,而其他模塊運行在內核空間,這些模塊之間利用共享內存傳輸需要的命令、狀態和錯誤信息。

本文通過對RTAI 提供的共享內存機制研究,設計并實現一種高效的共享內存管理機制,減少系統內核調用次數,提高了RTAI 的共享內存分配和釋放速率,將其應用于現有的數控系統,實現了數控系統的高可靠性。

1 RTAI 共享內存的實現機制

RTAI 是Linux 操作系統的一種實時擴展,它通過設置保留一塊物理內存,并將其映射到使用的進程地址空間,用來提供共享內存機制可用于內核和用戶空間的通信,維護了內核和用戶所申請內存的空間映射。在RTAI 中,rtai_kmalloc 是從內核空間分配共享內存的接口函數,rtai_malloc 是從用戶空間分配共享內存的接口函數。rtai_kmalloc 從內核申請小于KMALLOC_LIMIT(128K)的空間使用系統內核函數kmalloc 分配共享內存空間,大于KMALLOC_LIMIT 使用內核系統函數__get_free_pages 分配空間。rtai_malloc 從用戶空間申請時,直接使用系統函數vmalloc 分配。無論從內核或者是用戶分配完,都要設置頁面保留位,標識出該頁不被置換出。對于已經被分配的,則函數查找維護的全局變量,將共享內存地址返回[1]。

共享內存機制也存在不足,其自身不能實現多進程的讀寫同步,需要應用程序自己解決復雜的同步互斥問題[2]。同時,每次新申請內存空間都要通過系統調用,這樣所需要的頁表分配的開銷比較大,同時增加了系統的負擔。

為解決同步互斥和多次系統調用的問題,本文研究并實現一個共享內存管理層,完成對共享內存的高效管理。

2 共享內存管理層設計

該層的設計就是實現一個共享內存的管理器,用戶不再使用由RTAI 提供的共享內存接口函數,而使用由該層實現的接口函數。主要包含數據結構設計,共享內存的分配算法設計和釋放算法設計。

2.1 數據結構設計

依據共享內存塊的相關屬性,從以下五個方面的數據特性考慮數據結構的設計:

(1)共享內存塊的性質,模塊主要有兩種,內核模塊或者是用戶模塊,申請共享內存空間的模塊選擇涉及到實際分配所使用的RTAI 函數。

(2)共享內存塊的并發訪問,不同的模塊對一塊數據的并發訪問,保證各個部分對同一個數據的一致性訪問??刹捎没コ饬?,來保證同一時間只有一個進程來訪問一個關鍵區域,防止產生臟數據。若對訪問的數據不是嚴格要求,可以使訪問的進程獲取上次產生的舊數據,不必忙等,減少系統的負擔,增加系統的吞吐率。

(3)共享內存塊的分配和訪問效率。確定共享內存分配的大小,以及維護內存塊的個數,不使用某一塊,將占用計數減一,為零時并不立即釋放,只是標明未使用,再次申請使用只用占用計數加一,就可繼續使用,減少系統函數的反復調用,增加整個系統的穩定性。在此基礎上,增加共享內存池的概念,它是已經由底層分配函數分配成功的大塊的共享內存,當上層若要申請的共享內存大小小于該內存池的大小,則直接從中分配空間給用戶。同時也要維護共享內存塊的鏈表,在釋放的時候能將合適的塊合并。

(4)統計數據。利于系統對數據的統計分析,以便于對當前系統的性能分析和問題排查。同時也是最終是否能夠釋放共享內存的標志。

(5)共享內存塊標識。唯一的確定一塊內存,在內核空間和用戶空間維護共享內存塊地址與使用者之間的映射。

2.2 數據結構

主要使用共享內存池和共享內存塊這兩種結構來實現管理層的設計。

共享內存池:由共享內存層利用系統分配函數分配的大塊共享內存,使用雙向循環鏈表連接,由共享內存層負責地址映射。若存在的內存池空間不能滿足需要,內存池可再利用底層系統函數進行分配;共享內存池的可用空間大小是指被申請使用的共享內存塊使用余下的可被再分配的空間,同時考慮到邊界對齊;使用互斥量來保證對內存的并發訪問。

共享內存塊:在已存在的內存池里分配的用戶申請的內存空間,采用雙向循環鏈表連接,存在空閑鏈表,是被用戶釋放的,但并沒有被共享管理層實際釋放,只是置位該塊可以繼續使用,同時要考慮相鄰空閑塊的合并,和非空閑的共享內存塊鏈表。

為了保證共享內存塊的分配效率,共享內存管理層要維護一定數量的空閑內存池,使得系統免于重復的內存分配和釋放,該數量的設置要考慮到系統的負載,可由實際系統需要設置。

整個數據模型如圖1 所示。

圖1 共享內存管理層數據結構模型

2.3 分配算法設計

2.3.1 共享內存池分配算法

共享內存空間的實際分配,在內核空間利用底層共享內存接口函數rtai_kmalloc 分配共享內存,在用戶空間使用rtai_malloc。

2.3.2 共享內存塊分配算法

首先,在共享內存標識符表中,查找是否已經分配了申請字符串名的共享內存,若已經分配,修改相應計數并返回地址;否則,采用首次適配算法,首先在第一個共享內存池的空閑鏈表中,查看是否有符合要求的內存塊,若有直接將占用計數加一,同時加入到非空閑鏈表的合適位置。否則,依次查看存在的共享內存池,從共享內存池的可用空間判斷是否符合用戶要求,若符合,從中減去用戶申請的大小,注意字節對齊,并同時加入到非空閑內存塊鏈表的合適位置,返回地址。若不符合,則重新申請一個符合大小規則的新的共享內存池,分配適合用戶使用的內存塊,同時加入到非空閑塊鏈表的合適位置,按照可用空閑塊地址將內存池插入到合適的位置,返回地址,見圖2。

2.4 釋放算法設計

2.4.1 共享內存池釋放算法

共享內存池的釋放是共享內存空間的實際釋放,如果當前使用計數為0,在內核空間利用底層共享內存接口函數rtai_kfree,在用戶空間利用底層共享內存接口函數rtai_free。

2.4.2 共享內存塊釋放算法

利用共享內存標示符表查找此名標示的共享內存塊,若找到,將共享內存塊的占用計數減一,若未找到,則說明未分配共享內存,失敗返回,為零放入到合適的空閑塊鏈表,若有相鄰的空閑塊,將其連成一個連續的空閑塊,放入合適的位置,否則,直接返回。若空閑塊地址與內存池可用地址鄰接,將其歸還給共享內存池。最后,清除共享內存標示符表保存的名和地址的映射,見圖3。

圖2 共享內存塊分配算法流程圖

圖3 共享內存塊釋放算法

2.5 關鍵API 設計

void * get_shmem_addr(char * name,unsigned int size),獲得大小為size,指針名為name 的共享內存地址。

int free_shmem_addr(char * name),釋放指針名為name 的共享內存。

void * _get_shmem_addr(unsigned int size),實際進行共享內存分配。

shmem_block * find_with_name(const char *name),查找是否已經存在name 指向的字符串名的共享內存。

int get_shmem_pool(int pol),獲得一個共享內存池。

int free_shmem_pool(shmem_pool * p),釋放內存池分配的共享內存空間。

shmem_block* get_shmem_block(unsigned int size,module_type mod),獲取一個size 大小,性質為mod 的內存塊。

int free_shmem_block(shmem_block * b),將內存塊釋放,就是將它放入空閑塊鏈表里

shmem_block* search_in_shmem_pool(shmem_pool * p,unsigned int size),在空閑塊鏈表里面查找是否有合適的空閑塊

int insert_shmem_block_into_pool(shmem_block* b,shmem_pool* p),將分配好的內存塊插入到內存池的內存塊鏈表里。

int insert_free_shmem_block_into_pool(shmem_block* b,shmem_pool* p),將空閑塊插入到內存池的空閑塊鏈表里

int free_shmem_pool_block(shmem_pool* p),將和內存池可用空間地址毗鄰的空閑內存塊返回給內存池。

void * get_addr_shmem_block(shmem_block *b),獲取共享塊所指向的地址。

void init_shmem_block(shmem_block * b,unsigned int size,module_type mod,unsigned int pol),初始化內存塊。

shmem_block* alloc_shmem_block_from_pool(shmem_pool * p,unsigned int size),從合適的內存池里分配內存塊。

API 接口調用如下圖4 和圖5 所示。

圖4 分配過程API 調用

3 實驗及應用

硬件平臺為龍芯CPU,主頻800MHZ,內存256M,軟件環境為linux2.4 操作系統,RTAI-24.1.13實時擴展。整個共享內存管理層使用C 語言實現,具有很強的移植性。

實驗計時方法,利用MIPS 體系結構的協處理器0(Coprocessor 0)的count(9)寄存器[8]。在分配之前獲取時間戳t1,在分配之后獲取時間戳t2,兩者之差就是所需要的時間Δt。

圖5 釋放過程API 調用

實驗結果如下圖6 和圖7 所示。

圖6 rtai 和shmem 分配和釋放4 字節的時間

圖7 rtai 和shmem 分配和釋放400 字節的時間

由圖6 和圖7 可知,利用shmem 共享內存管理,能夠有效的減少共享內存的分配時間和釋放時間。

4 結束語

共享內存在需要內核和用戶空間數據傳輸的情況下,有較高的靈活性,所以在數控系統中應用廣泛,因此提高共享內存的管理效率對各種使用共享內存的應用具有很重要的意義。本文采用兩級數據管理結構,能夠有效的分配和釋放共享內存,使用C語言實現的該共享內存管理層具有很好的可移植性,能夠有效的減少共享內存分配和釋放時間,同時互斥量的使用也能保證共享內存的并發訪問。實驗結果證明,本設計優化了RTAI 共享內存管理的相關功能,提高了數控系統的工作效率。

[1]RTAI documentation,available from:https://www. rtai.org/documentation/magma/html/api/

[2]高甜容,于東,等. 數控系統中模塊間通信方法的設計與實現[J]. 計算機工程,2010,36(12):238-241.

[3]Mauerer W. Professional Linux Kernel Architecture[M].[S. l.]:John Wiley & Sons Inc.,2008.

[4]Yu Dong,Hu Yi,Huang Yan,et al. An Open CNC System Based on Component Technology[J]. IEEE,2009,6(2):302-311.

[5]Scott S,Christos D A,Dimitrios S N. Scalable Locality-conscious Multithreaded Memory Allocation[C]. ACM,2006:84-94.

[6]魯比尼(Rubini,A.),等,著,魏永明,等,譯. LINUX 設備驅動程序[M]. 北京:中國電力出版社,2002.

[7]魏海濤,姜昱明,李建武,等. 內存管理機制的高效實現研究[J]. 計算機工程與設計,2009,30(16):3708-3712.

[8]吳文江,秦承剛,陶耀東. 基于MIPS 處理器和RTAI 的數控系統中調度抖動的研究[J]. 小型微型計算機系統,2010(7):1342-1345.

猜你喜歡
鏈表空閑數控系統
如何用鏈表實現一元多項式相加
“鳥”字謎
跟麥咭學編程
西灣村采風
彪悍的“寵”生,不需要解釋
基于FANUC 32i A數控系統的外部測量設計
西門子840D sl數控系統在SC125大型車銑鏜床技術改造中的應用
基于FANUC Oi mate TD數控系統的手動功能開發
數控系統中GUI軟件平臺設計和實現
基于MTF規則的非阻塞自組織鏈表
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合