写在前面
本系列记录了作者在项目过程中由于好奇心驱使而了解到的部分DPDK实现细节。比较适合有同样好奇心的DPDK的初学者,通过本系列文章
您可以学习到
DPDK的整体工作原理以及部分实现细节
您不能学习到
应用DPDK进行性能调优
如果对DPDK的起源不是很清楚的话,可以先浏览下 绝对干货!初学者也能看懂的DPDK解析,重点就是Linux + x86网络IO瓶颈 这部分,总结一句话就是Linux内核协议栈太慢了,为了突破这种性能瓶颈,DPDK的方案是绕过(bypass)内核,直接从网卡把数据抓到用户空间。
一些基本的概念
EAL
首先必须明白的一点就是,DPDK是以若干个lib的形式提供给应用链接使用,其中最终要的一个lib就是EAL了,EAL的全称是(Environment Abstraction Layer, 环境抽象层),它负责为应用间接访问底层的资源,比如内存空间、线程、设备、定时器等。如果把我们的应用比作一个豪宅的主人的话,EAL就是这个豪宅的管家。
lcore & socket
这两个概念在 DPDK的代码中随处可见,注意这里的 socket 不是网络编程里面的那一套东西,而是CPU相关的东西。具体的概念可以参看Differences between physical CPU vs logical CPU vs Core vs Thread vs Socket 或者其翻译版本physical CPU vs logical CPU vs Core vs Thread vs Socket(翻译)。
对我们来说,只要知道可以DPDK可以运行在多个lcore上就足够了.
DPDK 如何知道有多少个lcore呢 ? 在启动时解析文件系统中的特定文件就可以了, 参考函数eal_cpu_detected
DPDK的运行形式
大部分DPDK的代码是以lib的形式运行在用户应用的进程上下文.为了达到更高的性能。应用通常都会多进程或者多线程的形式运行在不同的lcore上
多线程的场景:
多进程的场景:
多进程的场景下,多个应用实例如何保证关键信息(比如内存资源)的一致性呢? 答案是不同进程将公共的数据mmap同一个文件,这样任何一个进程对数据的修改都可以影响到其他进程。
Primary & Secondary
多进程场景下,进程有两种角色Primary或者Secondary,正如其名字,Primary进程可以create 资源,而Secondary进程只能 attach已存在的资源。一山不容二虎,一个多进程的应用,有且只有一个Primary进程,其余都是Secondary进程。应用可以通过命令行参数 –proc-type 来指定应用类型。
DPDK的入口
如同main函数在应用程序中的地位,rte_eal_init函数便是DPDK梦开始的地方(其实前面的图已经画出来了!),我们来看看它做了什么事。
/* Launch threads, called at application init(). */
int
rte_eal_init(int argc, char **argv)
{
thread_id = pthread_self();
rte_eal_cpu_init();
eal_parse_args(argc, argv);
rte_config_init();
rte_eal_intr_init();
rte_mp_channel_init();
rte_eal_memzone_init();
rte_eal_memory_init();
rte_eal_malloc_heap_init()
eal_thread_init_master(rte_config.master_lcore);
RTE_LCORE_FOREACH_SLAVE(i) {
/* create a thread for each lcore */
ret = pthread_create(&lcore_config[i].thread_id, NULL,
eal_thread_loop, NULL);
…..
}
/*
* Launch a dummy function on all slave lcores, so that master lcore
* knows they are all ready when this function returns.
*/
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
rte_eal_mp_wait_lcore();
……
}
总结起来就是
检测lcore
解析用户的命令行参数
内存资源等子模块初始化
在其他lcore上启动线程
发表回复