扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
rte_eal_init()
创新互联专注为客户提供全方位的互联网综合服务,包含不限于网站建设、成都做网站、加格达奇网络推广、微信小程序开发、加格达奇网络营销、加格达奇企业策划、加格达奇品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们大的嘉奖;创新互联为所有大学生创业者提供加格达奇建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com接上次内容继续对rte_eal_init所做的工作进行分析。
6. 将DPDK进程的启动参数保留下来
在启动DPDK进程时会传入启动参数,这些参数会分成两部分,一部分是DPDK的eal配置参数,如占用的CPU处理核的列表,分配的大页内存大小,网卡的黑白名单等;另外一部分是进程自定义参数,由开发者自行定义参数列表和含义。参数列表中eal配置参数放在前面,进程自定义参数在后面,中间通过“--”进行分割。
eal_save_args()中,分配两段内存空间并交给两个全局的变量eal_args和eal_app_args,后将两部分参数分别存放在这两段内存空间当中。
7. CPU处理核信息初始化
存在一个全局数组变量lcore_config,类型为struct lcore_config,大小由宏定义RTE_MAX_LCORE指定。在rte_eal_cpu_init()中,首先依次遍历数组中的每个元素并对struct lcore_config中的一些元素赋默认值。该结构体的数据结构包含如下内容:
struct lcore_config {
pthread_t thread_id; // lcore绑定线程的标识符
int pipe_main2worker[2]; // 从main到worker管道标识
int pipe_worker2main[2]; // 从worker到main的管道标识
lcore_function_t * volatile f; // lcore绑定线程的入口函数
void * volatile arg; // 入口函数的传入参数
volatile int ret; // 线程入口函数的返回值
volatile enum rte_lcore_state_t state; // lcore的状态
unsigned int socket_id; // 该lcore所属CPU的socket id
unsigned int core_id; // 该lcore在CPU上的物理核
int core_index; // 该lcore的相对索引,从0开始
uint8_t core_role; // 该lcore的角色,可选项有OFF, RTE, SERVICE
rte_cpuset_t cpuset; // 该lcore对应的主机CPU的lcore的mask
};
要理解该结构体中一些元素的含义,首先需要了解一下CPU的结构。在Linux中执行lscpu命令,可得到如下输出内容:
root@Soc:~# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 46 bits physical, 57 bits virtual
CPU(s): 16
On-line CPU(s) list: 0-15
Thread(s) per core: 2
Core(s) per socket: 8
Socket(s): 1
该例子的主机中,有一个socket。socket可以对应主板上的一个CPU插槽,也就是一块CPU芯片。对于一般的PC机来说,只有一个socket,大型服务器一般有多个socket。一个socket中一般会有多个core,即一个独立的处理单元,在单线程模式下,一个独立的处理单元包含一套标准的寄存器和L1级缓存,同时刻只能运行一个线程;而多线程模式下,一套处理单元有两套寄存器,同时刻可以运行两个线程,这两个线程共享L1级缓存。上例中所显示的主机的CPU有8个处理单元,因为开启了多线程,每个处理单元线程数是2,这样逻辑上讲一共有16个线程(或CPU)。
对应到lcore_config中的相关结构,socket_id即为socket的编号,core_id对应的是处理单元的编号,而DPDK的处理核lcore则对应的是线程(或CPU)的编号。
在遍历lcore_config的每个元素时的索引就是lcore的编号,遍历时,根据lcore的编号去系统中查找对应的线程(或CPU)。如果该线程没有被启用,则将lcore_config结构体中的core_index置位负数,并将rte_config中的lcore_role中对应的值置为ROLE_OFF;线程被启用时,core_index设置为相对索引,lcore_role设为ROLE_RTE。
遍历完lcore之后,也就能够统计出涉及到的socket有哪些了,会根据这些信息设置rte_config中的numa_node信息。
需要另外指出的是,rte_eal_cpu_init()中涉及到的某些func,是通过直接访问sys文件系统实现的。如eal_cpu_socket_id()是遍历/sys/devices/system/node/nodeX目录中如果存在cpuY目录,则lcoreY的socket id是X;eal_cpu_detected()是遍历/sys/devices/system/cpu/cpuX/topology/core_id是否存在。
8. DPDK参数解析
eal_parse_args()是解析DPDK参数,比较重要的几个参数有:
-a:allow list,指定哪些网卡设备是允许被DPDK接管的,传入的参数值是设备的pci总线编号。
-b:block list,指定哪些网卡设备是进制被DPDK禁止的,传入值同上。
-c:指定DPDK进程所占用的处理核是哪些,用bitmask的方式进行表示。
-m:指定分配多大的内存空间给DPDK的内存池,以MB为单位。
解析之后的信息存放在internal_config这个全局变量或者其他的变量当中。DPDK涉及到的参数比较多,后续会根据需要补充说明各参数的含义。
9. 插件初始化
如果是Windows系统,是不支持插件动态载入的,eal_plugins_init()的内容为空。是Linux系统时,如果能通过执行系统调用dlopen打开动态链接库librte_eal.so.XX,则调用eal_plugin_add将默认动态库的目录default_solib_dir添加到全局变量solib_list当中(此外还可以通过DPDK的启动参数-d,将自定义目录添加到solib_list中)。
由于在初始化阶段加入solib_list中的可能是动态库本身也可能是动态库所在的目录,eal_plugins_init()会在遍历solib_list中将目录中的*.so文件全部遍历之后加入solib_list中;如果已经是*.so本身,则设置solib的lib_handle。
10. 初始化跟踪功能
调用eal_trace_init()初始化跟踪功能,该功能是对一些事件和变量进行跟踪,用于多线程同步和时间度量等。该功能比较复杂,后续分析过程中会详细介绍,此处先略过。
11. 解析设备
前面提到DPDK的参数时,-a和-b参数分别指定网卡设备的白黑名单,这些信息是存放在devopt_list这个全局变量当中的,eal_option_device_parse()会遍历其中的每个设备,并转换成新的数据结构存放在devargs_list当中。
未完待续…
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流