DPDK的RTE INIT初始化

2021-09-10 18:06:38 字數 4798 閱讀 5680

dpdk**中廣泛使用rte_init巨集進行裝置驅動或者rte模組等的初始化工作,其核心是rte_init_prio巨集,定義在檔案rte_common.h中。如下可見,rte_init_prio巨集的實現,實際為乙個附帶gcc編譯屬性的函式定義。此處用到兩個屬性,constructor和used。其中後乙個used比較簡單,向gcc編譯器表明此函式的有用性,即使函式沒有被任何地方引用,也不要警告。constructor構造屬性,類似c++的建構函式,其標註的函式將在主函式(main)之前執行,相關**位於目標檔案的.ctors區(section)。

lib/librte_eal/common/include/rte_common.h

#define rte_init_prio(func, prio) \

static void __attribute__((constructor(rte_prio(prio)), used)) func(void)

另外rte_prio巨集指定了constructor的優先順序,即函式執行的順序,值越小優先順序越高。目前定義了4個優先順序:rte_priority_log、rte_priority_bus、rte_priority_class和rte_priority_last。

#define rte_priority_log 101

#define rte_priority_bus 110

#define rte_priority_class 120

#define rte_priority_last 65535

#define rte_prio(prio) rte_priority_ ## prio

其中rte_init巨集封裝了rte_priority_last優先順序的函式。rte_register_bus巨集封裝了rte_priority_bus優先順序的函式。而rte_register_class巨集封裝了rte_priority_class優先順序的函式。目前dpdk中rte_priority_log優先順序的函式僅有乙個rte_log_init,優先順序最高,最先初始化(函式所在檔案:lib/librte_eal/common/eal_common_log.c)。

#define rte_init(func) rte_init_prio(func, last)

lib/librte_eal/common/include/rte_bus.h

#define rte_register_bus(nm, bus) \

rte_init_prio(businitfn_ ##nm, bus) \

lib/librte_eal/common/include/rte_class.h

#define rte_register_class(nm, cls) \

rte_init_prio(classinitfn_ ##nm, class) \

如下編譯dpdk的examples,如vhost程式,檢視生成的map檔案(vhost-switch.map),檢查constructor屬性生成的初始化建構函式:

$ cd examples/vhost

$ export rte_sdk=/home/k/network/dpdk-19.02

$ export rte_target=build

$ make

cc main.o

cc virtio_net.o

ld vhost-switch

install-map vhost-switch.map

$

如下所示,可見按照優先順序順序排列的初始化函式,優先順序最低的rte_priority_last未顯示其數值。

.init_array     0x000000000099e400      0x670

0x000000000099e400 provide (__init_array_start, .)

*(sort(.init_array.*) sort(.ctors.*))

.init_array.00101

0x000000000099e400 0x8 /home/k/network/dpdk-19.02/build/lib/librte_eal.a(eal_common_log.o)

.init_array.00110

0x000000000099e408 0x8 /home/k/network/dpdk-19.02/build/lib/librte_bus_pci.a(pci_common.o)

.init_array.00110

0x000000000099e410 0x8 /home/k/network/dpdk-19.02/build/lib/librte_bus_vdev.a(vdev.o)

.init_array.00110

0x000000000099e418 0x8 /home/k/network/dpdk-19.02/build/lib/librte_bus_dpaa.a(dpaa_bus.o)

.init_array.00110

0x000000000099e420 0x8 /home/k/network/dpdk-19.02/build/lib/librte_bus_fslmc.a(fslmc_bus.o)

.init_array.00110

0x000000000099e428 0x8 /home/k/network/dpdk-19.02/build/lib/librte_bus_vmbus.a(vmbus_common.o)

.init_array.00110

0x000000000099e430 0x8 /home/k/network/dpdk-19.02/build/lib/librte_bus_ifpga.a(ifpga_bus.o)

.init_array.00120

0x000000000099e438 0x8 /home/k/network/dpdk-19.02/build/lib/librte_ethdev.a(rte_class_eth.o)

*(.init_array exclude_file(*crtend?.o *crtend.o *crtbegin?.o *crtbegin.o) .ctors)

.init_array 0x000000000099e440 0x8 /usr/lib/gcc/x86_64-linux-gnu/7/crtbegins.o

.init_array 0x000000000099e448 0x8 /home/k/network/dpdk-19.02/build/lib/librte_ip_frag.a(ip_frag_internal.o)

.init_array 0x000000000099e450 0x8 /home/k/network/dpdk-19.02/build/lib/librte_lpm.a(rte_lpm.o)

通過檢視dpdk**可見,各個函式在vhost-switch.map中的順序與其在**中的註冊的優先順序相符。

lib/librte_eal/common/eal_common_log.c rte_init_prio(rte_log_init, log)

drivers/bus/pci/pci_common.c rte_register_bus(pci, rte_pci_bus.bus);

drivers/bus/vdev/vdev.c rte_register_bus(vdev, rte_vdev_bus);

drivers/bus/dpaa/dpaa_bus.c rte_register_bus(fsl_dpaa_bus_name, rte_dpaa_bus.bus);

drivers/bus/fslmc/fslmc_bus.c rte_register_bus(fslmc_bus_name, rte_fslmc_bus.bus);

drivers/bus/vmbus/vmbus_common.c rte_register_bus(vmbus, rte_vmbus_bus.bus);

drivers/bus/ifpga/ifpga_bus.c rte_register_bus(ifpga_bus_name, rte_ifpga_bus);

lib/librte_ethdev/rte_class_eth.c rte_register_class(eth, rte_class_eth);

另外,dpdk中定義了rte_fini相關巨集,其使用了gcc的destructor和used兩個屬性,used的意義與rte_init中的相同。destructor屬性表明函式在主函式(main)結束之後執行。不過目前,在dpdk**中並沒有地方使用rte_fini巨集。

lib/librte_eal/common/include/rte_common.h

#define rte_fini_prio(func, prio) \

static void __attribute__((destructor(rte_prio(prio)), used)) func(void)

#define rte_fini(func) rte_fini_prio(func, last)

lib/librte_eal/common/include/rte_class.h

#define rte_unregister_class(nm, cls) \

rte_fini_prio(classfinifn_ ##nm, class) \

dpdk版本dpdk-19.02。

dpdk記憶體管理 初始化

dpdk的記憶體初始化工作,主要是將hugetlbfs的配置的大記憶體頁,根據其對映的實體地址是否連續 屬於哪個socket等,有效的組織起來,為後續管理提供便利。eal hugepage info init 主要是獲取配置好的hugetlbfs的相關資訊,並將其儲存在struct internal...

DPDK裝置驅動的匹配和初始化

前言 dpdk使用了uio 使用者空間i o 的機制,跳過核心態的網絡卡驅動,轉而使用使用者態的收發包驅動,從驅動到記憶體和資料報,繼而到資料報的處理,這是乙個完整的收發包流程。這篇主要介紹裝置驅動的初始化,和收發包的處理。所選 以dpdk 17.02版本為依據。資料報的驅動初始化是在rte eal...

DPDK收發包處理流程 網絡卡初始化

本文基於dpdk 1.8.0分析。網絡卡驅動模型一般包含三層,即,pci 匯流排裝置 網絡卡裝置以及網絡卡裝置的私有資料結構,即將裝置的共性一層層的抽象,pci 匯流排裝置包含網絡卡裝置,網絡卡裝置又包含其私有資料結構。在 dpdk 中,首先會註冊裝置驅動,然後查詢當前系統有哪些 pci設 備,並通...