作者|donatello1996
來源 | 電子發(fā)燒友
題圖|飛凌嵌入式
rte_ring是一個(gè)用CAS實(shí)現(xiàn)的無鎖FIFO環(huán)形隊(duì)列,支持多消費(fèi)者/生產(chǎn)者同時(shí)出入隊(duì)列,常用于多線程/多進(jìn)程之間的通信。具體原理可以查看DPDK官方文檔或者閱讀源碼,本文采用的硬件板卡為飛凌嵌入式OKMX8MP-C開發(fā)板,系統(tǒng)版本Linux5.4.70+Qt5.15.0,主要介紹通過編譯DPDK源碼實(shí)現(xiàn)rte_ring無鎖環(huán)隊(duì)列進(jìn)程間通信。
下面就跟著小編一起了解下。
一、內(nèi)核編譯下載并解壓飛凌廠商提供的iMX8MP內(nèi)核源碼壓縮包分卷:
在虛擬機(jī)中合并壓縮分卷并解壓得出內(nèi)核源碼包文件夾OK8MP-linux-kernel,將文件夾使用tar打包并復(fù)制到TF卡文件系統(tǒng)中解壓:
找到內(nèi)核源碼中的配置文件OK8MP-C_defconfig:
這個(gè)就是make選項(xiàng),使用
make OK8MP-C_defconfig
指令即可配置編譯選項(xiàng):
make -j4
開始編譯:
注意開始編譯前需要安裝常用軟件:
apt install bison bc flex
增量編譯完畢:
接下來就可以下載DPDK并運(yùn)行rte_ring無鎖環(huán)隊(duì)列Demo應(yīng)用,需要從
https://www.dpdk.org/
官網(wǎng)中下載DPDK 19.11.10 (LTS)長(zhǎng)期支持版本:
在根目錄下的mk/文件夾下找到名為rte_vars.mk設(shè)置文件,找到環(huán)境變量RTE_KERNELDIR,修改為上述的內(nèi)核源碼路徑:
![aef06c42-6fd6-11ec-86cf-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/9C/5E/wKgaomTnyCmAHts8AADD3VEaqlY581.jpg)
RTE_KERNELDIR ?= /home/OK8MP-linux-kernel/
進(jìn)入usertools文件夾,找到dpdk-setup.sh腳本并運(yùn)行
選擇8,ARM64-armv8a-linuxapp-gcc,
這個(gè)選項(xiàng)會(huì)使dpdk的gcc交叉編譯鏈生成適用于armv8a處理器的外部庫(kù),外部庫(kù)中有kmod和lib等ko文件和so文件,是用于第三方程序開發(fā)和運(yùn)行的:
使用指令
insmod /home/dpdk-stable-19.11.10/arm64-armv8a-linuxapp-gcc/kmod/igb_uio.ko
左右滑動(dòng)查看完整代碼加載igb_uio.ko驅(qū)動(dòng)文件,這是進(jìn)行dpdk開發(fā)必備的步驟:
然后是使用dpdk-devbind.py腳本手動(dòng)進(jìn)行hugepage大頁(yè)內(nèi)存綁定,此處為numa方式:
此舉會(huì)將/mnt/huge文件mount成hugepage映射文件,并實(shí)實(shí)在在地占用內(nèi)存空間:
準(zhǔn)備工作完成,我們接下來可以進(jìn)行rte_ring無鎖環(huán)隊(duì)列Demo代碼的編寫,但是在編寫之前,需要對(duì)無鎖環(huán)隊(duì)列有一個(gè)基本的認(rèn)識(shí):https://blog.csdn.net/chen98765432101/article/details/69367633
無論是dpdk第三方開發(fā)的rte_ring還是Linux內(nèi)核中本就存在的無鎖環(huán)隊(duì)列,其基本原理類似,在一條分配好的隊(duì)列型內(nèi)存空間中,讀寫方式為FIFO(先進(jìn)先出),讀和寫的動(dòng)作分別有兩個(gè)進(jìn)程或兩個(gè)線程進(jìn)行,寫進(jìn)程不斷往地址自增的內(nèi)存位置寫入數(shù)據(jù),讀進(jìn)程不斷讀取地址自增的內(nèi)存位置的數(shù)據(jù),當(dāng)寫位置的內(nèi)存地址已為隊(duì)列中內(nèi)存的最高值時(shí),需要釋放隊(duì)列中內(nèi)存地址最低值的空間供寫進(jìn)程繼續(xù)寫,方式仍與上一周期相同(不斷往地址自增的內(nèi)存位置寫入數(shù)據(jù)),釋放過程需要保證對(duì)末尾內(nèi)存地址空間的鎖定與解鎖,避免讀寫過程出錯(cuò)。而不同的是,Linux內(nèi)核中的無鎖環(huán)隊(duì)列,地址管理和讀寫控制均由內(nèi)核進(jìn)行,而dpdk的rte_ring則由dpdk內(nèi)部的控制器進(jìn)行,因?yàn)閐pdk這一模塊完整地接管了所分配內(nèi)存空間的管理權(quán),是直接繞過Linux內(nèi)核進(jìn)行管理的,內(nèi)核也無權(quán)訪問dpdk控制器的具體管理細(xì)節(jié)。
編寫無鎖環(huán)隊(duì)列兩個(gè)進(jìn)程的Demo,先寫Primary進(jìn)程:
左右滑動(dòng)查看完整代碼
static const char *_MSG_POOL = "MSG_POOL";
static const char *_SEC_2_PRI = "SEC_2_PRI";
static const char *_PRI_2_SEC = "PRI_2_SEC";
static const char *_PRI_2_THI = "PRI_2_THI";
struct rte_ring *send_ring, *recv_ring , *send_ring_third;
struct rte_mempool *message_pool;
volatile int quit = 0;
static void * lcore_recv(void *arg)
{
unsigned lcore_id = rte_lcore_id();
printf("Starting core %u\n", lcore_id);
while (!quit){
void *msg;
if (rte_ring_dequeue(recv_ring, &msg) < 0)
{
usleep(5);
continue;
}
printf("lcore_id = %d Received '%s'\n" , lcore_id , (char *)msg);
rte_mempool_put(message_pool , msg);
}
return 0;
}
int string_size = 100;
int elt_size = 128;
pthread_t id1;
int main(int argc, char **argv)
{
const unsigned flags = 0;
const unsigned ring_size = 64;
const unsigned pool_size = 1024;
const unsigned pool_cache = 32;
const unsigned priv_data_sz = 0;
int ret;
unsigned lcore_id;
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot init EAL\n");
send_ring = rte_ring_create(_PRI_2_SEC, ring_size, rte_socket_id(), flags);
recv_ring = rte_ring_create(_SEC_2_PRI, ring_size, rte_socket_id(), flags);
send_ring_third = rte_ring_create(_PRI_2_THI, ring_size, rte_socket_id(), flags);
message_pool = rte_mempool_create(_MSG_POOL, pool_size,
elt_size, pool_cache, priv_data_sz,
NULL, NULL, NULL, NULL,
rte_socket_id(), flags);
if (send_ring == NULL)
rte_exit(EXIT_FAILURE, "Problem getting sending ring\n");
if (recv_ring == NULL)
rte_exit(EXIT_FAILURE, "Problem getting receiving ring\n");
if (send_ring_third == NULL)
rte_exit(EXIT_FAILURE, "Problem getting send_ring_third\n");
if (message_pool == NULL)
rte_exit(EXIT_FAILURE, "Problem getting message pool\n");
pthread_create(&id1 , NULL , lcore_recv , NULL);
while(1)
{
void *msg = NULL;
if (rte_mempool_get(message_pool, &msg) < 0)
continue;
snprintf((char *)msg, string_size, "%s", "primary to secondary");
if (rte_ring_enqueue(send_ring , msg) < 0)
{
rte_mempool_put(message_pool, msg);
}
if (rte_mempool_get(message_pool, &msg) < 0)
continue;
snprintf((char *)msg, string_size, "%s", "primary to third");
if (rte_ring_enqueue(send_ring_third , msg) < 0)
{
rte_mempool_put(message_pool, msg);
}
sleep(1);
}
return 0;
}
注意在Makefile文件里面要關(guān)閉WERROR相關(guān)編譯選項(xiàng):
左右滑動(dòng)查看完整代碼# BSD LICENSE
#
# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
# Default target, can be overridden by command line or environment
RTE_TARGET ?= arm64-armv8a-linuxapp-gcc
include $(RTE_SDK)/mk/rte.vars.mk
# binary name
APP = rte_ring_primary
# all source are stored in SRCS-y
SRCS-y := main.c
CFLAGS += -O0
CFLAGS +=
include $(RTE_SDK)/mk/rte.extapp.mk
Secondary進(jìn)程:
static const char *_MSG_POOL = "MSG_POOL";
static const char *_SEC_2_PRI = "SEC_2_PRI";
static const char *_PRI_2_SEC = "PRI_2_SEC";
struct rte_ring *send_ring, *recv_ring;
struct rte_mempool *message_pool;
volatile int quit = 0;
int string_size = 100;
static int lcore_send(__attribute__((unused)) void *arg)
{
unsigned lcore_id = rte_lcore_id();
while(1)
{
void *msg = NULL;
if (rte_mempool_get(message_pool, &msg) < 0)
continue;
snprintf((char *)msg , string_size , "%s", "secondary to primary");
if (rte_ring_enqueue(send_ring , msg) < 0)
{
rte_mempool_put(message_pool, msg);
}
sleep(1);
}
return 0;
}
pthread_t id1;
int main(int argc, char **argv)
{
const unsigned flags = 0;
const unsigned ring_size = 64;
const unsigned pool_size = 1024;
const unsigned pool_cache = 32;
const unsigned priv_data_sz = 0;
int ret;
unsigned lcore_id;
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot init EAL\n");
recv_ring = rte_ring_lookup(_PRI_2_SEC);
send_ring = rte_ring_lookup(_SEC_2_PRI);
message_pool = rte_mempool_lookup(_MSG_POOL);
if (send_ring == NULL)
rte_exit(EXIT_FAILURE, "Problem getting sending ring\n");
if (recv_ring == NULL)
rte_exit(EXIT_FAILURE, "Problem getting receiving ring\n");
if (message_pool == NULL)
rte_exit(EXIT_FAILURE, "Problem getting message pool\n");
pthread_create(&id1 , NULL , lcore_send , NULL);
while (1)
{
lcore_id = rte_lcore_id();
void * msg = NULL;
if (rte_ring_dequeue(recv_ring, &msg) < 0)
{
usleep(5);
continue;
}
printf("lcore_id = %d Received: %s\n" , lcore_id , (char *)msg);
rte_mempool_put(message_pool, msg);
}
return 0;
}
左右滑動(dòng)查看完整代碼
同樣在Makefile文件里面要關(guān)閉WERROR相關(guān)編譯選項(xiàng):
左右滑動(dòng)查看完整代碼# BSD LICENSE
#
# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
# Default target, can be overridden by command line or environment
RTE_TARGET ?= arm64-armv8a-linuxapp-gcc
include $(RTE_SDK)/mk/rte.vars.mk
# binary name
APP = rte_ring_secondary
# all source are stored in SRCS-y
SRCS-y := main.c
CFLAGS += -O3
CFLAGS += $()
include $(RTE_SDK)/mk/rte.extapp.mk
運(yùn)行,這里說一下,基于rte_ring的進(jìn)程間通信,Secondary進(jìn)程最好是使用auto類型:
./rte_ring_primary --proc-type primary
./rte_ring_secondary --proc-type auto
運(yùn)行效果:
![b254fb0a-6fd6-11ec-86cf-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/9C/5E/wKgaomTnyCuATy-kAADATZGdaEk786.jpg)
作者簡(jiǎn)介
donatello1996,某大型企業(yè)資深嵌入式工程師,電子發(fā)燒友論壇技術(shù)大牛,同時(shí)也是飛凌嵌入式多年鐵粉,曾基于飛凌多款板卡產(chǎn)出過優(yōu)質(zhì)測(cè)評(píng)文章或使用心得。本期三篇文章為donatello1996在使用OKMX8MP-C開發(fā)板過程中精心產(chǎn)出的干貨,在此對(duì)donatello1996表示感謝。
-
嵌入式
+關(guān)注
關(guān)注
5096文章
19189瀏覽量
308028
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
[求職] RK3588核心板,尋找志同道合的電子發(fā)燒友!
電子發(fā)燒友社區(qū)2025年春節(jié)放假通知!
榜樣力量,智領(lǐng)未來——2024年度電子發(fā)燒友社區(qū)表彰
AN-1420:利用數(shù)字鎖相環(huán)(DPLL)實(shí)現(xiàn)相位增建和無中斷切換
![AN-1420:利用數(shù)字鎖相<b class='flag-5'>環(huán)</b>(DPLL)<b class='flag-5'>實(shí)現(xiàn)</b>相位增建和<b class='flag-5'>無</b>中斷切換](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
電子發(fā)燒友榮獲機(jī)械工業(yè)出版社 華章板塊“2024年度優(yōu)秀合作伙伴獎(jiǎng)”
面向NXP i.MX8處理器的電源解決方案
![面向NXP <b class='flag-5'>i.MX8</b>處理器的電源解決方案](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
華秋電子 | 電子發(fā)燒友亮相OpenHarmony人才生態(tài)大會(huì)2024
基于AR1335和i.MX8MP的視覺方案
![基于AR1335和<b class='flag-5'>i.MX8MP</b>的視覺方案](https://file.elecfans.com/web2/M00/65/09/pYYBAGMHLo-AXhv6AABF60N1Sbg429.png)
強(qiáng)大視覺方案:i.MX8MP與AR0144的完美結(jié)合
![強(qiáng)大視覺方案:<b class='flag-5'>i.MX8MP</b>與AR0144的完美結(jié)合](https://file.elecfans.com/web2/M00/65/09/pYYBAGMHLo-AXhv6AABF60N1Sbg429.png)
i.MX Linux開發(fā)實(shí)戰(zhàn)指南—基于野火i.MX系列開發(fā)板
恩智浦i.MX8處理器的集成電源設(shè)計(jì)
![恩智浦<b class='flag-5'>i.MX8</b>處理器的集成電源設(shè)計(jì)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
使用TPS6521825和LP873347 PMIC為NXP i.MX 8M Mini和Nano供電
![使用TPS6521825和LP873347 PMIC為NXP <b class='flag-5'>i.MX</b> <b class='flag-5'>8</b>M Mini和Nano供電](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
使用TPS65219為i.MX 8M Plus供電
![使用TPS65219為<b class='flag-5'>i.MX</b> <b class='flag-5'>8</b>M Plus供電](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評(píng)論