飞凌嵌入式
直播中

donatello1996

9年用户 737经验值
擅长:MEMS/传感技术
私信 关注
[技术]

【飞凌嵌入式OKMX8MP-C 开发板试用体验】编译内核源码&编译DPDK源码实现rte_ring无锁环队列进程间通信

本帖最后由 donatello1996 于 2021-11-23 14:09 编辑

下载并解压飞凌厂商提供的内核源码压缩包分卷:
10.JPG
在虚拟机中合并压缩分卷并解压得出内核源码包文件夹OK8MP-linux-kernel,将文件夹使用tar打包并复制到TF卡文件系统中解压:
11.JPG
找到内核源码中的配置文件OK8MP-C_defconfig:
12.JPG


这个就是make选项,使用
  1. make OK8MP-C_defconfig
指令即可配置编译选项:
  1. make -j4
开始编译:

注意开始编译前需要安装常用软件:
  1. apt install bison bc flex
8.JPG 9.JPG
增量编译完毕:
13.JPG

然后接下来就可以下载DPDK并运行rte_ring无锁环队列Demo应用,需要从
https://www.dpdk.org/
官网中下载DPDK 19.11.10 (LTS)长期支持版本:
14.JPG

在根目录下的mk/文件夹下找到名为rte_vars.mk设置文件,找到环境变量RTE_KERNELDIR,修改为上述的内核源码路径:
18.JPG

  1. RTE_KERNELDIR ?= /home/OK8MP-linux-kernel/
19.JPG
进入usertools文件夹,找到dpdk-setup.sh脚本并运行:
15.JPG 16.JPG
选择8,ARM64-armv8a-linuxapp-gcc,这个选项会使dpdk的gcc交叉编译链生成适用于armv8a处理器的外部库,外部库中有kmod和lib等ko文件和so文件,是用于第三方程序开发和运行的:
17.JPG 20.JPG
使用指令
  1. insmod /home/dpdk-stable-19.11.10/arm64-armv8a-linuxapp-gcc/kmod/igb_uio.ko
加载igb_uio.ko驱动文件,这是进行dpdk开发必备的步骤:
22.JPG

然后是使用dpdk-devbind.py脚本手动进行hugepage大页内存绑定,此处为numa方式:
23.JPG

此举会将/mnt/huge文件mount成hugepage映射文件,并实实在在地占用内存空间:
24.JPG
25.JPG

准备工作完成,我们接下来可以进行rte_ring无锁环队列Demo代码的编写,但是在编写之前,需要对无锁环队列有一个基本的认识:https://blog.csdn.net/chen98765432101/article/details/69367633

无论是dpdk第三方开发的rte_ring还是Linux内核中本就存在的无锁环队列,其基本原理类似,在一条分配好的队列型内存空间中,读写方式为FIFO(先进先出),读和写的动作分别有两个进程或两个线程进行,写进程不断往地址自增的内存位置写入数据,读进程不断读取地址自增的内存位置的数据,当写位置的内存地址已为队列中内存的最高值时,需要释放队列中内存地址最低值的空间供写进程继续写,方式仍与上一周期相同(不断往地址自增的内存位置写入数据),释放过程需要保证对末尾内存地址空间的锁定与解锁,避免读写过程出错。而不同的是,Linux内核中的无锁环队列,地址管理和读写控制均由内核进行,而dpdk的rte_ring则由dpdk内部的控制器进行,因为dpdk这一模块完整地接管了所分配内存空间的管理权,是直接绕过Linux内核进行管理的,内核也无权访问dpdk控制器的具体管理细节。
26.JPG
28.JPG 29.JPG 30.JPG 31.JPG 32.JPG

编写无锁环队列两个进程的Demo,先写Primary进程:
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #include

  11. #include
  12. #include

  13. #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1

  14. static const char *_MSG_POOL = "MSG_POOL";
  15. static const char *_SEC_2_PRI = "SEC_2_PRI";
  16. static const char *_PRI_2_SEC = "PRI_2_SEC";
  17. static const char *_PRI_2_THI = "PRI_2_THI";

  18. struct rte_ring *send_ring, *recv_ring , *send_ring_third;
  19. struct rte_mempool *message_pool;
  20. volatile int quit = 0;

  21. static void * lcore_recv(void *arg)
  22. {
  23.         unsigned lcore_id = rte_lcore_id();

  24.         printf("Starting core %un", lcore_id);
  25.         while (!quit){
  26.                 void *msg;
  27.                 if (rte_ring_dequeue(recv_ring, &msg) < 0)
  28.                 {
  29.                         usleep(5);
  30.                         continue;
  31.                 }
  32.                 printf("lcore_id = %d Received '%s'n" , lcore_id , (char *)msg);
  33.                 rte_mempool_put(message_pool , msg);
  34.         }

  35.         return 0;
  36. }

  37. int string_size = 100;
  38. int elt_size = 128;
  39. pthread_t id1;

  40. int main(int argc, char **argv)
  41. {
  42.         const unsigned flags = 0;
  43.         const unsigned ring_size = 64;
  44.         const unsigned pool_size = 1024;
  45.         const unsigned pool_cache = 32;
  46.         const unsigned priv_data_sz = 0;

  47.         int ret;
  48.         unsigned lcore_id;

  49.         ret = rte_eal_init(argc, argv);
  50.         if (ret < 0)
  51.                 rte_exit(EXIT_FAILURE, "Cannot init EALn");

  52.         send_ring = rte_ring_create(_PRI_2_SEC, ring_size, rte_socket_id(), flags);
  53.         recv_ring = rte_ring_create(_SEC_2_PRI, ring_size, rte_socket_id(), flags);
  54.         send_ring_third = rte_ring_create(_PRI_2_THI, ring_size, rte_socket_id(), flags);
  55.         message_pool = rte_mempool_create(_MSG_POOL, pool_size,
  56.                         elt_size, pool_cache, priv_data_sz,
  57.                         NULL, NULL, NULL, NULL,
  58.                         rte_socket_id(), flags);

  59.         if (send_ring == NULL)
  60.                 rte_exit(EXIT_FAILURE, "Problem getting sending ringn");

  61.         if (recv_ring == NULL)
  62.                 rte_exit(EXIT_FAILURE, "Problem getting receiving ringn");

  63.         if (send_ring_third == NULL)
  64.                 rte_exit(EXIT_FAILURE, "Problem getting send_ring_thirdn");

  65.         if (message_pool == NULL)
  66.                 rte_exit(EXIT_FAILURE, "Problem getting message pooln");

  67.         pthread_create(&id1 , NULL , lcore_recv , NULL);
  68.         while(1)
  69.         {
  70.                 void *msg = NULL;
  71.                 if (rte_mempool_get(message_pool, &msg) < 0)
  72.                         continue;
  73.                
  74.                 snprintf((char *)msg, string_size, "%s", "primary to secondary");
  75.                 if (rte_ring_enqueue(send_ring , msg) < 0)
  76.                 {
  77.                         rte_mempool_put(message_pool, msg);
  78.                 }

  79.                 if (rte_mempool_get(message_pool, &msg) < 0)
  80.                         continue;
  81.                
  82.                 snprintf((char *)msg, string_size, "%s", "primary to third");
  83.                 if (rte_ring_enqueue(send_ring_third , msg) < 0)
  84.                 {
  85.                         rte_mempool_put(message_pool, msg);
  86.                 }

  87.                 sleep(1);
  88.         }

  89.         return 0;
  90. }

注意在Makefile文件里面要关闭WERROR相关编译选项:
  1. #   BSD LICENSE
  2. #
  3. #   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
  4. #   All rights reserved.
  5. #
  6. #   Redistribution and use in source and binary forms, with or without
  7. #   modification, are permitted provided that the following conditions
  8. #   are met:
  9. #
  10. #     * Redistributions of source code must retain the above copyright
  11. #       notice, this list of conditions and the following disclaimer.
  12. #     * Redistributions in binary form must reproduce the above copyright
  13. #       notice, this list of conditions and the following disclaimer in
  14. #       the documentation and/or other materials provided with the
  15. #       distribution.
  16. #     * Neither the name of Intel Corporation nor the names of its
  17. #       contributors may be used to endorse or promote products derived
  18. #       from this software without specific prior written permission.
  19. #
  20. #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  31. ifeq ($(RTE_SDK),)
  32. $(error "Please define RTE_SDK environment variable")
  33. endif

  34. # Default target, can be overridden by command line or environment
  35. RTE_TARGET ?= arm64-armv8a-linuxapp-gcc

  36. include $(RTE_SDK)/mk/rte.vars.mk

  37. # binary name
  38. APP = rte_ring_primary

  39. # all source are stored in SRCS-y
  40. SRCS-y := main.c

  41. CFLAGS += -O0
  42. CFLAGS +=

  43. include $(RTE_SDK)/mk/rte.extapp.mk


Secondary进程:
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #include

  11. #include
  12. #include

  13. #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1

  14. static const char *_MSG_POOL = "MSG_POOL";
  15. static const char *_SEC_2_PRI = "SEC_2_PRI";
  16. static const char *_PRI_2_SEC = "PRI_2_SEC";

  17. struct rte_ring *send_ring, *recv_ring;
  18. struct rte_mempool *message_pool;
  19. volatile int quit = 0;
  20. int string_size = 100;

  21. static int lcore_send(__attribute__((unused)) void *arg)
  22. {
  23.         unsigned lcore_id = rte_lcore_id();

  24.         while(1)
  25.         {
  26.                 void *msg = NULL;
  27.                 if (rte_mempool_get(message_pool, &msg) < 0)
  28.                         continue;
  29.                
  30.                 snprintf((char *)msg , string_size , "%s", "secondary to primary");
  31.                 if (rte_ring_enqueue(send_ring , msg) < 0)
  32.                 {
  33.                         rte_mempool_put(message_pool, msg);
  34.                 }
  35.                 sleep(1);
  36.         }
  37.         return 0;
  38. }

  39. pthread_t id1;

  40. int main(int argc, char **argv)
  41. {
  42.         const unsigned flags = 0;
  43.         const unsigned ring_size = 64;
  44.         const unsigned pool_size = 1024;
  45.         const unsigned pool_cache = 32;
  46.         const unsigned priv_data_sz = 0;

  47.         int ret;
  48.         unsigned lcore_id;
  49.         ret = rte_eal_init(argc, argv);
  50.         if (ret < 0)
  51.                 rte_exit(EXIT_FAILURE, "Cannot init EALn");

  52.         recv_ring = rte_ring_lookup(_PRI_2_SEC);
  53.         send_ring = rte_ring_lookup(_SEC_2_PRI);
  54.         message_pool = rte_mempool_lookup(_MSG_POOL);

  55.         if (send_ring == NULL)
  56.                 rte_exit(EXIT_FAILURE, "Problem getting sending ringn");
  57.         if (recv_ring == NULL)
  58.                 rte_exit(EXIT_FAILURE, "Problem getting receiving ringn");
  59.         if (message_pool == NULL)
  60.                 rte_exit(EXIT_FAILURE, "Problem getting message pooln");

  61.         pthread_create(&id1 , NULL , lcore_send , NULL);
  62.     while (1)
  63.         {
  64.                 lcore_id = rte_lcore_id();
  65.         void * msg = NULL;
  66.         if (rte_ring_dequeue(recv_ring, &msg) < 0)
  67.                 {
  68.             usleep(5);
  69.             continue;
  70.         }

  71.         printf("lcore_id = %d Received: %sn" , lcore_id , (char *)msg);
  72.      
  73.         rte_mempool_put(message_pool, msg);
  74.     }

  75.         return 0;
  76. }


同样在Makefile文件里面要关闭WERROR相关编译选项:
  1. #   BSD LICENSE
  2. #
  3. #   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
  4. #   All rights reserved.
  5. #
  6. #   Redistribution and use in source and binary forms, with or without
  7. #   modification, are permitted provided that the following conditions
  8. #   are met:
  9. #
  10. #     * Redistributions of source code must retain the above copyright
  11. #       notice, this list of conditions and the following disclaimer.
  12. #     * Redistributions in binary form must reproduce the above copyright
  13. #       notice, this list of conditions and the following disclaimer in
  14. #       the documentation and/or other materials provided with the
  15. #       distribution.
  16. #     * Neither the name of Intel Corporation nor the names of its
  17. #       contributors may be used to endorse or promote products derived
  18. #       from this software without specific prior written permission.
  19. #
  20. #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  31. ifeq ($(RTE_SDK),)
  32. $(error "Please define RTE_SDK environment variable")
  33. endif

  34. # Default target, can be overridden by command line or environment
  35. RTE_TARGET ?= arm64-armv8a-linuxapp-gcc

  36. include $(RTE_SDK)/mk/rte.vars.mk

  37. # binary name
  38. APP = rte_ring_secondary

  39. # all source are stored in SRCS-y
  40. SRCS-y := main.c

  41. CFLAGS += -O3
  42. CFLAGS += $()

  43. include $(RTE_SDK)/mk/rte.extapp.mk


运行,这里说一下,基于rte_ring的进程间通信,Secondary进程最好是使用auto类型:
  1. ./rte_ring_primary --proc-type primary
  2. ./rte_ring_secondary --proc-type auto

运行效果:
34.JPG 33.JPG

  • 27.JPG
  • 21.JPG

回帖(2)

内个老胡

2021-11-23 11:17:31
写的真好,飞凌嵌入式iMX8MP开发板资源丰富,性能强悍,期待后续内容!!
举报

内个老胡

2021-11-23 11:18:38
写的真好,飞凌嵌入式iMX8MP开发板资源丰富,性能强悍,期待后续内容!!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分