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通過檢視dpdk**可見,各個函式在vhost-switch.map中的順序與其在**中的註冊的優先順序相符。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)
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設 備,並通...