DPDK timer 解析

2024-04-23 23:44
文章标签 解析 dpdk timer

本文主要是介绍DPDK timer 解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 编译 DPDK timer

设置环境变量:

  • export RTE_SDK=/home//dpdk/dpdk-stable-19.08.2/
  • export RTE_TARGET=x86_64-native-linux-gcc

源码路径:./dpdk 源码/examples/timer/

编译方法:在上面路径下执行 make

目标文件路径:./dpdk 源码/examples/timer/build/timer

下面是 timer 部分运行结果:

可以看到的是有两个定时器 timer0 和 timer1, timer0 是绑定到当前 cpu 核心一直是 core 0 触发定时器 0,

而 timer1 则是在不同核心触发定时器 1。

EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: PCI device 0000:02:01.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:02:06.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:03:00.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 15ad:7b0 net_vmxnet3
EAL: PCI device 0000:0b:00.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 15ad:7b0 net_vmxnet3
Starting mainloop on core 1
Starting mainloop on core 2
Starting mainloop on core 3
Starting mainloop on core 4
Starting mainloop on core 5
Starting mainloop on core 6
Starting mainloop on core 7
Starting mainloop on core 0
timer1_cb() on lcore 1
timer1_cb() on lcore 2
timer0_cb() on lcore 0
timer1_cb() on lcore 3
timer1_cb() on lcore 4
timer1_cb() on lcore 5
timer0_cb() on lcore 0
timer1_cb() on lcore 6
timer1_cb() on lcore 7
timer1_cb() on lcore 0

2. DPDK API 学习

2.1. rte_timer_subsystem_init()

#include <rte_timer.h>
int rte_timer_subsystem_init(void);
//作用:确保定时器子系统被正确初始化,从而保证后续的定时器操作能够正常进行。

2.2. rte_timer_init()

#include <rte_timer.h>
void rte_timer_init(struct rte_timer *tim);
// 作用:初始化一个rte_timer对象

2.3. rte_get_timer_hz()

#include <rte_cycles.h>
uint64_t rte_get_timer_hz(void);
// 作用:函数用于获取系统定时器的频率,即每秒钟CPU时钟周期的数量。

2.4. rte_timer_reset()

#include <rte_timer.h>
void rte_timer_reset(struct rte_timer *tim,uint64_t ticks,enum rte_timer_type type,unsigned lcore_id,rte_timer_cb_t *f,void *arg);
//作用:函数用于重新设置定时器的参数,包括定时器的周期、触发模式、回调函数以及回调函数的参数等
//参数:
/*
tim       :指向要重新设置的定时器对象的指针。
ticks     :表示定时器的周期,即定时器触发的时间间隔,单位是CPU时钟周期数。
type      :表示定时器的触发模式,是一个枚举类型。常见的触发模式有:SINGLE    :单次触发,定时器只会在下一个周期触发一次,然后停止。PERIODICAL:周期性触发,定时器会在每个周期都触发一次,直到手动停止。
lcore_id  :表示定时器触发时要在哪个CPU核心上执行回调函数。
f         :是一个函数指针,指向定时器触发时要执行的回调函数。
arg       :是传递给回调函数的参数,可以是任意类型的指针,用于传递额外的数据给回调函数
*/

2.5. rte_timer_manage()

#include <rte_timer.h>
void rte_timer_manage(void);
//作用:管理系统中所有的定时器,检查是否有定时器已经到期(即触发),如果有则执行相应的回调函数。

3. 源代码

3.1. 使用 timer0 和 timer1

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/queue.h>#include <rte_common.h>
#include <rte_memory.h>
#include <rte_launch.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_cycles.h>
#include <rte_timer.h>
#include <rte_debug.h>#define TIMER_RESOLUTION_CYCLES 20000000ULL /* around 10ms at 2 Ghz */static struct rte_timer timer0;
static struct rte_timer timer1;/* timer0 callback */
static void timer0_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg)
{static unsigned counter = 0;unsigned lcore_id = rte_lcore_id();printf("%s() on lcore %u\n", __func__, lcore_id);/* this timer is automatically reloaded until we decide to* stop it, when counter reaches 20. */if ((counter ++) == 20)rte_timer_stop(tim);
}/* timer1 callback */
static void timer1_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg)
{unsigned lcore_id = rte_lcore_id();uint64_t hz;printf("%s() on lcore %u\n", __func__, lcore_id);/* reload it on another lcore */hz = rte_get_timer_hz();lcore_id = rte_get_next_lcore(lcore_id, 0, 1);rte_timer_reset(tim, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
}static __attribute__((noreturn)) int lcore_mainloop(__attribute__((unused)) void *arg)
{uint64_t prev_tsc = 0, cur_tsc, diff_tsc;unsigned lcore_id;lcore_id = rte_lcore_id();printf("Starting mainloop on core %u\n", lcore_id);while (1) {/** Call the timer handler on each core: as we don't* need a very precise timer, so only call* rte_timer_manage() every ~10ms (at 2Ghz). In a real* application, this will enhance performances as* reading the HPET timer is not efficient.*/cur_tsc = rte_rdtsc();diff_tsc = cur_tsc - prev_tsc;if (diff_tsc > TIMER_RESOLUTION_CYCLES) {rte_timer_manage();prev_tsc = cur_tsc;}}
}int main(int argc, char **argv)
{int ret;uint64_t hz;unsigned lcore_id;/* init EAL */ret = rte_eal_init(argc, argv);if (ret < 0)rte_panic("Cannot init EAL\n");/* init RTE timer library */rte_timer_subsystem_init();/* init timer structures */rte_timer_init(&timer0);rte_timer_init(&timer1);/* load timer0, every second, on master lcore, reloaded automatically *//* 每秒加载定时器0,绑定当前核心,自动加载 */hz = rte_get_timer_hz();lcore_id = rte_lcore_id();rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL);/* load timer1, every second/3, on next lcore, reloaded manually *//* 每3秒加载定时器0,绑定下一个核心,手动加载 */lcore_id = rte_get_next_lcore(lcore_id, 0, 1);rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL);/* call lcore_mainloop() on every slave lcore */RTE_LCORE_FOREACH_SLAVE(lcore_id) {rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);}/* call it on master lcore too */(void) lcore_mainloop(NULL);return 0;
}

3.2. 只使用 timer0

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/queue.h>#include <rte_common.h>
#include <rte_memory.h>
#include <rte_launch.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_cycles.h>
#include <rte_timer.h>
#include <rte_debug.h>#define TIMER_RESOLUTION_CYCLES 20000000ULL /* around 10ms at 2 Ghz */static struct rte_timer timer0;/* timer0 callback */
static void timer0_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg)
{static unsigned counter = 0;unsigned lcore_id = rte_lcore_id();printf("%s() on lcore %u\n", __func__, lcore_id);/* this timer is automatically reloaded until we decide to* stop it, when counter reaches 20. */if ((counter ++) == 20)rte_timer_stop(tim);
}static __attribute__((noreturn)) int lcore_mainloop(__attribute__((unused)) void *arg)
{uint64_t prev_tsc = 0, cur_tsc, diff_tsc;unsigned lcore_id;lcore_id = rte_lcore_id();printf("Starting mainloop on core %u\n", lcore_id);while (1) {/** Call the timer handler on each core: as we don't* need a very precise timer, so only call* rte_timer_manage() every ~10ms (at 2Ghz). In a real* application, this will enhance performances as* reading the HPET timer is not efficient.*/cur_tsc = rte_rdtsc();diff_tsc = cur_tsc - prev_tsc;if (diff_tsc > TIMER_RESOLUTION_CYCLES) {rte_timer_manage();prev_tsc = cur_tsc;}}
}int main(int argc, char **argv)
{int ret;uint64_t hz;unsigned lcore_id;/* init EAL */ret = rte_eal_init(argc, argv);if (ret < 0)rte_panic("Cannot init EAL\n");/* init RTE timer library */rte_timer_subsystem_init();/* init timer structures */rte_timer_init(&timer0);/* load timer0, every second, on master lcore, reloaded automatically *//* 每秒加载定时器0,绑定当前核心,自动加载 */hz = rte_get_timer_hz();lcore_id = rte_lcore_id();rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL);/* call lcore_mainloop() on every slave lcore */RTE_LCORE_FOREACH_SLAVE(lcore_id) {rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);}/* call it on master lcore too */(void) lcore_mainloop(NULL);return 0;
}
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: PCI device 0000:02:01.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:02:06.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:03:00.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 15ad:7b0 net_vmxnet3
EAL: PCI device 0000:0b:00.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 15ad:7b0 net_vmxnet3
Starting mainloop on core 1
Starting mainloop on core 2
Starting mainloop on core 3
Starting mainloop on core 4
Starting mainloop on core 7
Starting mainloop on core 0
Starting mainloop on core 5
Starting mainloop on core 6
timer0_cb() on lcore 0
timer0_cb() on lcore 0
timer0_cb() on lcore 0
timer0_cb() on lcore 0
timer0_cb() on lcore 0
timer0_cb() on lcore 0
timer0_cb() on lcore 0

3.3. 只使用 timer1

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/queue.h>#include <rte_common.h>
#include <rte_memory.h>
#include <rte_launch.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_cycles.h>
#include <rte_timer.h>
#include <rte_debug.h>#define TIMER_RESOLUTION_CYCLES 20000000ULL /* around 10ms at 2 Ghz */static struct rte_timer timer1;/* timer1 callback */
static void timer1_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg)
{unsigned lcore_id = rte_lcore_id();uint64_t hz;printf("%s() on lcore %u\n", __func__, lcore_id);/* reload it on another lcore */hz = rte_get_timer_hz();lcore_id = rte_get_next_lcore(lcore_id, 0, 1);rte_timer_reset(tim, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
}static __attribute__((noreturn)) int lcore_mainloop(__attribute__((unused)) void *arg)
{uint64_t prev_tsc = 0, cur_tsc, diff_tsc;unsigned lcore_id;lcore_id = rte_lcore_id();printf("Starting mainloop on core %u\n", lcore_id);while (1) {/** Call the timer handler on each core: as we don't* need a very precise timer, so only call* rte_timer_manage() every ~10ms (at 2Ghz). In a real* application, this will enhance performances as* reading the HPET timer is not efficient.*/cur_tsc = rte_rdtsc();diff_tsc = cur_tsc - prev_tsc;if (diff_tsc > TIMER_RESOLUTION_CYCLES) {rte_timer_manage();prev_tsc = cur_tsc;}}
}int main(int argc, char **argv)
{int ret;uint64_t hz;unsigned lcore_id;/* init EAL */ret = rte_eal_init(argc, argv);if (ret < 0)rte_panic("Cannot init EAL\n");/* init RTE timer library */rte_timer_subsystem_init();/* init timer structures */rte_timer_init(&timer1);hz = rte_get_timer_hz();lcore_id = rte_get_next_lcore(lcore_id, 0, 1);rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL);/* call lcore_mainloop() on every slave lcore */RTE_LCORE_FOREACH_SLAVE(lcore_id) {rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);}/* call it on master lcore too */(void) lcore_mainloop(NULL);return 0;
}
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: PCI device 0000:02:01.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:02:06.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:03:00.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 15ad:7b0 net_vmxnet3
EAL: PCI device 0000:0b:00.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 15ad:7b0 net_vmxnet3
Starting mainloop on core 1
Starting mainloop on core 3
Starting mainloop on core 4
Starting mainloop on core 5
Starting mainloop on core 2
Starting mainloop on core 6
Starting mainloop on core 7
Starting mainloop on core 0
timer1_cb() on lcore 1
timer1_cb() on lcore 2
timer1_cb() on lcore 3
timer1_cb() on lcore 4
timer1_cb() on lcore 5
timer1_cb() on lcore 6
timer1_cb() on lcore 7
timer1_cb() on lcore 0
timer1_cb() on lcore 1

这篇关于DPDK timer 解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/930213

相关文章

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Python利用ElementTree实现快速解析XML文件

《Python利用ElementTree实现快速解析XML文件》ElementTree是Python标准库的一部分,而且是Python标准库中用于解析和操作XML数据的模块,下面小编就来和大家详细讲讲... 目录一、XML文件解析到底有多重要二、ElementTree快速入门1. 加载XML的两种方式2.

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

java解析jwt中的payload的用法

《java解析jwt中的payload的用法》:本文主要介绍java解析jwt中的payload的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解析jwt中的payload1. 使用 jjwt 库步骤 1:添加依赖步骤 2:解析 JWT2. 使用 N

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Java字符串处理全解析(String、StringBuilder与StringBuffer)

《Java字符串处理全解析(String、StringBuilder与StringBuffer)》:本文主要介绍Java字符串处理全解析(String、StringBuilder与StringBu... 目录Java字符串处理全解析:String、StringBuilder与StringBuffer一、St