初次接触DPDK源码-Helloworld

初次接触DPDK源码-Helloworld

/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2010-2014 Intel Corporation
 */

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/queue.h>

#include <rte_memory.h>
#include <rte_launch.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_debug.h>

/* Launch a function on lcore. 8< */
static int
lcore_hello(__rte_unused void *arg)
{
	unsigned lcore_id;
	lcore_id = rte_lcore_id();
	printf("hello from core %u\n", lcore_id);
	return 0;
}
/* >8 End of launching function on lcore. */

/* Initialization of Environment Abstraction Layer (EAL). 8< */
int
main(int argc, char **argv)
{
	int ret;
	unsigned lcore_id;

	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_panic("Cannot init EAL\n");
	/* >8 End of initialization of Environment Abstraction Layer */

	/* Launches the function on each lcore. 8< */
	RTE_LCORE_FOREACH_WORKER(lcore_id) {
		/* Simpler equivalent. 8< */
		rte_eal_remote_launch(lcore_hello, NULL, lcore_id);
		/* >8 End of simpler equivalent. */
	}

	/* call it on main lcore too */
	lcore_hello(NULL);
	/* >8 End of launching the function on each lcore. */

	rte_eal_mp_wait_lcore();

	/* clean up the EAL */
	rte_eal_cleanup();

	return 0;
}

接下来进行分段逐行解析:

首先是lcode_hello函数,这一函数输出”hello from“信息,相当于是需要运行的目标函数。

static int
lcore_hello(__rte_unused void *arg)
{
	unsigned lcore_id;
	lcore_id = rte_lcore_id();
	printf("hello from core %u\n", lcore_id);
	return 0;
}
  1. static int:声明的是一个静态函数,静态函数的作用是保证该函数只在该源文件内起作用,即该homework.c文件中起作用,从而避免了万一被其他文件中的函数的重复调用。

    定义一个静态函数的好处是可以限制函数的作用域,避免函数名冲突,同时也可以提高程序的安全性和可维护性。

  2. __rte_unused void *arg:这是一个指针,而且是一个空指针。

    在这里放一个空指针的原因是在后面使用**rte_eal_remote_launch()**函数启动线程时,需要传递一个函数指针作为参数。但是在这个例子中并没有需要传递的参数,所以传递了一个空指针。

    并且在 **lcore_hello**函数内部,实际上没有使用这个参数,它只是为了满足启动线程时的函数参数要求。

  3. rte_lcore_id()这是一个函数,用来获取当前的lcore(逻辑线程)的ID,在DPDK的多线程环境中,可以通过这个函数来确定当前代码片段是在哪个逻辑核心上执行的,从而方便进行不同逻辑核心之间的通信、同步等操作。同时,也可以用它来确定逻辑核心的数量,方便进行任务分配和负载均衡等操作。

接下来是主函数中的部分:

int main(int argc, char **argv)
{
	int ret;
	unsigned lcore_id;

	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_panic("Cannot init EAL\n");

	RTE_LCORE_FOREACH_WORKER(lcore_id) {
		rte_eal_remote_launch(lcore_hello, NULL, lcore_id);
	}

	lcore_hello(NULL);

	rte_eal_mp_wait_lcore();
	rte_eal_cleanup();

	return 0;
}
  1. rte_eal_init(argc, argv):这个函数是用来初始化EAL环境,而EAL环境是什么呢?

    EAL全称为environment abstraction layer(环境抽象层),由于硬件之间的差异,会导致相同的软件运行在不同的硬件上会有差异,而环境抽象层就是将所有不同的硬件环境给进行抽象化处理,使得不同的硬件环境下仍能保持一致性。

    初始化EAL环境就是为了让程序能够使用 DPDK 提供的网络数据包处理功能,包括对网络接口的配置和管理,对收发数据包的处理等等。

    这个函数会返回一定的值,这个值会显示初始化是否成功,如果返回值小于0,则初始化失败

  2. 其中的 argc,argv 又是什么呢:

    这两个参数是用来传递命令行参数,其中argc是命令行参数的个数,而argv是一个char数组,是命令行参数的具体内容

    在DPDK官方文档中,给出来了这两个参数以及这个函数:

    int rte_eal_init(int argc, char **argv); 在这里,因为在main函数中已经定义好了,所以rte_eal_init函数中就没再重复定义。

  3. 下面来解释一下命令行参数是什么:命令行参数是在程序运行时,由用户通过命令行输入的一些参数,它们是用来控制程序行为的一种方式。通常情况下,命令行参数由一个或多个选项和参数组成,选项是由单个或多个字符组成的字符串,表示程序的某种行为或功能,参数是选项的附加信息,表示选项的具体参数值。例如说ls命令,可以增添命令行参数ls -i这个-i就是用来展示详细信息。

    在DPDK中,有时需要传入一些命令行参数,来指定使用的CPU核心或者内存通道,配置HugePages等等。

  4. rte_panic 这个是DPDK 库中的一个宏定义,它会打印一条错误信息并终止程序运行。它的作用是在程序出现严重错误时,及时地提示错误信息并终止程序,避免程序继续运行导致更严重的后果。

  5. RTE_LCORE_FOREACH_WORKER(lcore_id):RTE_LCORE_FOREACH_WORKER(lcore_id)是一个宏,用于循环迭代所有的工作线程(worker lcore)。它的作用是将一个给定的代码块在每个工作线程上执行一次,使得DPDK应用程序可以在多个线程上同时执行相同的代码块,在这里执行的代码块是底下的 rte_eal_remote_launch(lcore_hello, NULL, lcore_id)

    该宏需要一个参数 lcore_id,它代表了每个工作线程的编号。当使用该宏时,会自动循环遍历所有的工作线程,每次将一个工作线程的编号传递给 **lcore_id**变量,然后执行给定的代码块。

  6. rte_eal_remote_launch() 这是一个DPDK函数,用于在非主线程上,即另一个逻辑核心上启动一个函数,其原型定义为: int rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id);

    其中第一个为所要执行的函数,第二个为传入的参数,第三个为在哪个逻辑核心上启动函数。

    在上面的helloworld代码中,第一个就是lcore_hello,第二个参数为无”NULL“,第三个就是上一个宏中返回的值lcode_id

  7. 最后,再在主线程上运行一遍lcore_hello,要注意上面的宏只是用于所有逻辑线程上,主线程并没有执行函数。

  8. rte_eal_mp_wait_lcore() 函数,是等待所有逻辑线程上面的函数全部运行完,主线程在等待逻辑线程完成之后,会调用 **rte_eal_cleanup()**函数清除 DPDK 的资源。

  9. 补充:

    在DPDK中,主线程是初始化EAL(环境抽象层)并启动DPDK应用程序的线程。主线程启动后,DPDK应用程序会启动一些逻辑线程,这些逻辑线程将会处理应用程序的实际业务逻辑。主线程与每个逻辑线程的处理性能并不相等,因为在DPDK中,逻辑线程是专门为处理数据包而设计的,而主线程则负责管理和控制DPDK应用程序的全局状态。

    DPDK提供了一些API,可以让应用程序自主分配性能使得某个线程性能最优来完成最难的任务。例如,可以使用rte_lcore_has_role() API来检查某个线程是否拥有指定的角色,然后根据线程的角色分配不同的任务。此外,还可以使用rte_eal_remote_launch() API在指定的逻辑线程上启动指定的函数。通过这些API,应用程序可以根据需要自由地分配线程之间的工作负载,以达到最优的性能和资源利用率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值