1.ring提供的接口
對於一個模塊而言,其對外提供的接口直接表明了它所提供的功能,也是我們分析一個模塊最初的入口。ring是一個環形無鎖隊列,支持多生產者多消費者操作,所以對於隊列的操作構成了模塊的主要接口。ring的實現在文件rte_ring.c
和rte_ring.h
中。
rte_ring_create() //ring的創建
rte_ring_init() //ring的初始化
rte_ring_lookup() //ring的查找
rte_ring_free() //ring的釋放
rte_ring_dump() //獲取ring的使用信息
rte_ring_set_water_mark() //設置ring的水標
以上的幾個大的接口提供了ring的開始和結束以及查找。同時對於一個隊列來說,還有更多的入隊,出隊操作。如函數
rte_ring_mp_enqueue_burst()//多生產者批量入隊
此處就省略其他很多單(多)生產者,單(多)消費者的操作函數接口了。
2.ring的創建及初始化
rte ring的創建是通過rte_ring_create()
函數來實現的,這個函數的原型struct rte_ring * rte_ring_create(const char *name, unsigned count, int socket_id,unsigned flags)
這里需要注意的是socket_id
和flags
,在多個進程同時訪問同一個ring時,要改善性能,可以創建多個ring,同時要注意多個進程綁定在同一個socket上。另一個參數flags則是表明創建的ring是否安全支持多生產者多消費者模型。接下來就來看看創建及初始化中的一些細節。
首先找到ring_list
,ring_list
是掛接在隊列中的,根據ring不跨socket的原則,推斷是每個socket都維護有一個這樣的隊列,具體就不去摳代碼了,先主后次。
接下來就是兩個准備操作:
-
獲取創建的ring的空間大小,為后面分配空間做准備。
-
分配一個
struct rte_tailq_entry *te;
結構,在創建完成ring后,掛接這個隊列元素到隊列中去。此時不妨先看一下這個結構體的定義。struct rte_tailq_entry { TAILQ_ENTRY(rte_tailq_entry) next; /**< Pointer entries for a tailq list */ void *data; /**< Pointer to the data referenced by this tailq entry */ };
其中的data指針就指向了創建的ring的地址。
然后就是為新創建的ring分配內存空間咯,使用了rte_memzone_reserve()
函數分配,這個函數在內存部分詳細說明,但是需要注意:
rte_memzone_reserve()
只能用於primary進程中內存分配,也暗含了對於多生產者多消費者使用的ring,其ring的創建要在 primary進程中。
最后就是把分配的ring初始化-rte_ring_init()
,並填充te元素,把te掛接在隊列中。
3.ring的出入隊
ring的出入隊操作,我們重點來關注幾個接口:
__rte_ring_mp_do_enqueue()
__rte_ring_sp_do_enqueue()
__rte_ring_mc_do_dequeue()
__rte_ring_sc_do_dequeue()
無論使用的哪個上層接口,最終調用的就是這4個函數。在使用多生產者多消費者時,函數中會有rte_pause()
的操作,里面使用了__mm_pause()
指令,看注釋意思是避免忙等待,主要應用在短時的loops。至於具體的頭和尾指針的移動,可以參考prog_guide中的ring一節,圖文並茂。
4.ring的使用范圍以及潛在問題
-
1.ring的調試信息在non_EAL線程中是不支持獲取的。
-
2.ring支持多生產者入隊和多消費者出隊,但是都是不可搶占的。不可搶占的意思是:
- 一個線程在做多生產者入隊操作,此時,禁止被另一個做多生產者入隊的線程搶占。
- 一個線程在做多消費者出隊操作,此時,禁止被另一個做多消費者出隊的縣城搶占。
這意味着如果兩個線程在同一個core上操作,那么2th線程則必須等到1th線程調度后才能訪問,因此,盡量不要在同一個core上對同一個ring做多生產者同時入隊或者出隊。更詳細的說明,請參考 prog_guide 3.3.4章節。
5.關於水標的使用
在初始化ring的時候,可以設置對應的水標位置,但感覺它並未提供設置接口,用的地方不是很多。比如,當入隊已經達到水標位置時,就可以返回對應的錯誤值,上層調用就可以做些處理。