dpdk 中有提供time没看负责定时操作,同时在example/timer中有提供一个测试code
可以告知大家如何使用time 没看
从meson.build中可以看出源文件只有一个main.c
deps += 'timer'
sources = files(
'main.c'
)
从makefile中可以看出binary的名字叫timer,这个main.c 可以同时被build 为动态链接库和静态链接库
# binary name
APP = timer
# all source are stored in SRCS-y
SRCS-y := main.c
# Build using pkg-config variables if possible
$(shell pkg-config --exists libdpdk)
ifeq ($(.SHELLSTATUS),0)
all: shared
.PHONY: shared static
shared: build/$(APP)-shared
ln -sf $(APP)-shared build/$(APP)
static: build/$(APP)-static
ln -sf $(APP)-static build/$(APP)
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
与此同时可以看到优化级别是O3
timer的入口函数为main函数
int
main(int argc, char **argv)
{
int ret;
uint64_t hz;
unsigned lcore_id;
/* init EAL */
#初始化running time 环境
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_panic("Cannot init EAL\n");
#由于我们是测试timer,因此要用到rte提供的time子系统
/* init RTE timer library */
rte_timer_subsystem_init();
/* init timer structures */
#初始化两个timer的回调函数
rte_timer_init(&timer0);
rte_timer_init(&timer1);
/* load timer0, every second, on master lcore, reloaded automatically */
#timer 0在主核上(本例中是当前cpu),不一定是cpu0,自动状态
hz = rte_get_timer_hz();
#获取当前cpu
lcore_id = rte_lcore_id();
#设置timer运行的模式,例如这里就是周期运行PERIODICAL,周期是1s
rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL);
/* load timer1, every second/3, on next lcore, reloaded manually */
#timer1 在主cpu的下一个cpu上,如果主cpu 是0 的话,则下一个cpu可能是1
lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
#设置timer运行的模式,例如这里就是单次运行,如果要周期运行的话,需要在timer1的回调函数中继续调用rte_timer_reset
#设置timer,运行周期是0.33s
rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
/* call lcore_mainloop() on every slave lcore */
#再出了当前cpu上外的cpu上跑lcore_mainloop
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);
}
/* call it on master lcore too */
#在当前cpu上跑
(void) lcore_mainloop(NULL);
return 0;
}
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);
}
我们看一下timer0_cb的实现,运行20次就到期了,每次一秒的话,则20s后这个timer就停止了
我们看看lcore_mainloop的实现,如上所示每个cpu上都会跑一个lcore_mainloop
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;
#从这里知道dpdk中通过rte_timer_manage来管理当前core上的定时器,并且定时器的分辨率是TIMER_RESOLUTION_CYCLES
if (diff_tsc > TIMER_RESOLUTION_CYCLES) {
rte_timer_manage();
prev_tsc = cur_tsc;
}
}
}