在 DPDK Programmer's Guides 中的 EAL 一篇中有一個圖可以很清晰地看到一個DPDK的應用程序的大致執行思路:
初始化檢查CPU支持、微架構配置等完成后,執行main()函數。
- 第一步是
rte_eal_init()
,核心初始化和啟動。其中線程使用的是pthread庫,創造線程,并設置CPU親和性:DPDK通常每個核心固定一個pthread,以避免任務切換的開銷。 - 然后是 other inits,其余對象的初始化(mbuf、mempool、ring、lpm hash table等)都應該作為主 lcore 上整體應用程序初始化的一部分來完成。
rte_eal_remote_lauch(func, NULL, lcore_id)
,在每個邏輯核上注冊一個回調函數。rte_eal_mp_wait_lcore()
,等待各個線程返回。- 繼續其余的部分。
下面對照此思路閱讀 /dpdk/examples/helloworld/main.c 這個代碼:
/* 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>static int
lcore_hello(__attribute__((unused)) void *arg)
{unsigned lcore_id;lcore_id = rte_lcore_id(); // ⑤ 返回當前執行單元的線程IDprintf("hello from core %u\n", lcore_id);return 0;
}int
main(int argc, char **argv)
{int ret;unsigned lcore_id;ret = rte_eal_init(argc, argv); // ① 初始化EALif (ret < 0)rte_panic("Cannot init EAL\n");RTE_LCORE_FOREACH_SLAVE(lcore_id) { // ② 瀏覽除主lcore之外的所有lcorerte_eal_remote_launch(lcore_hello, NULL, lcore_id); // ③ 在lcore上執行函數}lcore_hello(NULL);rte_eal_mp_wait_lcore(); // ④ 等待lcore完成工作return 0;
}
① rte_eal_init()
初始化環境抽象層(EAL)。此函數僅在應用程序的main()函數中盡快在MASTER lcore上執行。
② 宏:RTE_LCORE_FOREACH_SLAVE(i)
:瀏覽除主lcore之外的所有正在運行的lcores。
#define RTE_LCORE_FOREACH_SLAVE(i)
Value:
for (i = rte_get_next_lcore(-1, 1, 0); \i<RTE_MAX_LCORE; \i = rte_get_next_lcore(i, 1, 0))
③ rte_eal_remote_launch(lcore_hello, NULL, lcore_id);
在另一個lcore上啟動一個函數。應僅在MASTER lcore上執行。第一個參數是函數名,第二個參數是以什么參數執行該函數,第三個參數是邏輯核的ID。
④ rte_eal_mp_wait_lcore();
應僅在MASTER lcore上執行,等到lcore完成它的工作。一個lcore有三種狀態:WAIT、RUNNING、FINISHED,對應空閑、正在執行一個函數、執行完成。依據三個狀態來協調線程的launch和wait。
⑤ rte_lcore_id()
返回執行單元的線程ID
API 文檔:
- DPDK Programmer's Guides - initialization-and-core-launching
- EAL環境抽象層 包括上文的 ①
- CPU-multicore:lcore ②、⑤
- CPU-multicore:launch ③、④