gdb前的准备
如果想要调试到dpdk源码的内部,则需要在编译的时候指定一些命令行参数:
meson -Dexamples=all -Dbuildtype=debug build
这样我们就可以进入到 ./build/app进行gdb调试了:
无情gdb
rte_cpu_is_supported
dpdk运行时会检查cpu是否支持,它通过cpuid将cpu的具体信息存放在4个寄存器中,这里feat leaf为1即EBX=1存放处理器签名(Processor Signiture)和功能(Feature)位。dpdk实现建立一个fearture_map,即检查哪个寄存器的某一位来查看cpu是否支持dpdk功能。
(免费订阅,永久学习)学习地址: Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家-学习视频教程-腾讯课堂
__atomic_compare_exchange_n
原子操作,run_once置1
pthread_self
获取主线程的线程id,他肯定是主线程,因为还没创建别的线程呢。
rte_eal_cpu_init
这一步是读取cpu信息,并填充到每一个lcore_config[lcoreid]中,我的虚拟机是1个真实CPU虚拟出的4个逻辑cpu,numa有1个节点node0,包含cpu0,cpu1,cpu2,cpu3。
可见DPDK的逻辑核赋值为4个,其中coreid即实体cpu id只有一个,且numa node也只有一个。dpdk实现默认情况下,dpdk逻辑核映射到CPU中为一一对应,因此cpuset分别1,2,4,8 -》cpu0,cpu1,cpu2,cpu3->lcore0, lcore1,lcore2,lcore3。后面未用到的lcore的index会置为-1。
eal_parse_args
这一步是进行命令行解析,我一般运行时加的时会用 -c f -n 4指定可以被dpdk接管的CPU以及内存读写采用4通道。命令行解析的关键函数为
opt = getopt_long(argc, argvopt, eal_short_options, eal_long_options, &option_index))
它通过事先指定的短命令和长命令进行解析,其中optionindex为解析到长option在eallong_options数组的索引,opt为解析到短option字符即c和n:
-
对于c指定cpu掩码来说,首先看是否与之前的已经设为服务核,接着调用eal_parse_coremask,解析得到新的ldcore[],再用新值去更新update_lcore_config,如果dpdk逻辑核为-1对应内部配置逻辑核应该ROLE_OFF。如果是缺省的,那么会调用eal_auto_detect_cores获取可用的逻辑核,关键函数为pthread_getaffinity_np可以获取当前线程可以被哪些CPU调度,并默认lcoreid0为master core.
-
对于n指定内存通道数时,实现很简单conf->force_nchannel = atoi(optarg);
-
接着会创建运行时目录,run_dir
XDG_RUNTIME_DIR:指向用户专用用户可写目录的路径,该目录与计算机上的用户登录时间绑定。它是在用户首次登录时自动创建的,并在用户的最终注销时被删除。如果用户登录一次,然后再次注销,然后再次登录,则目录之间的内容将丢失
-
DPDK的线程分为控制线程和数据线程,控制线程默认绑定到MASTER核上,除非仍有CPU可用,主要逻辑为首先将之前绑定的cpuset和控制线程的cpuset做或运算,然后取反,接着与当前线程的调度cpuset作与运算。
eal_plugins_init
插件机制,就是动态库,首先会通过NOLOAD加载.so测试当前运行程序是否是动态链接库加载dpdk,如果是静态库加载直接返回,否则将会加载插件,插件的路径可以由-d参数指定,也可以由RTE_EAL_PMD_PATH(/usr/local/lib64/dpdk/pmds-21.0)指定,函数会加载-d指定的so或者将指定路径下满足条件的插件加入管理(eal_plugin_add),并通过dlopen加载
eal_trace_init
这个函数是对一些事件或变量进行跟踪,一般用于多线程同步,等待时间测量等。DPDK使用的是CTF格式 ,为了记录非常频繁的底层操作,一般开销为20个时钟周期。使用option OPT_TRACE_NUM和OPT_TRACE_DIR_NUM可以开启这个功能,这部分实现太复杂了,后续debug dpdk-test时专门写一个跟踪器的分析。我这边直接return掉。