DPDK多进程支持

一. 介绍

在DPDK中,多进程支持旨在允许一组DPDK进程以简单的透明方式协同工作,来处理数据包或其他工作负载。为了支持此功能,已经对核心DPDK环境抽象层(EAL)进行了一些增加。

EAL已被修改为允许不同类型的DPDK进程被产生,每个DPDK进程在应用程序使用的hugepage内存上具有不同的权限。 现在有两种类型的进程指定:

a.主进程,他能初始化和拥有共享内存的所有权限;

b.辅进程,不能初始化共享内存,但是能访问已初始化的共享内存和在其中创建对象。

独立DPDK进程是主进程,而辅助进程只能与主进程一起运行,或者主进程已经为其配置了hugepage共享内存。

为支持这两种进程类型,以及后面描述的多进程设置,EAL提供了附加的命令行:

--proc-type: 为进程指定类型,是主或辅。

--file-prefix:允许不想合作的进程有不同的内存区域。

1.共享内存

使用dpdk来开发多进程应用程序的关键是保证内存资源能够在多个进程之间正确的使用。一旦在多个进程间有共享的内存块访问,那面多个进程内部通讯(IPC)将变得相当简单。

在主进程或独立进程中的应用程序启动时,DPDK将内存配置文件的详细信息记录到内存映射文件 - 使用的hugepages,映射的虚拟地址,存在的内存通道数等。当从进程启动时,这些文件被读取,并且EAL在从进程中重新创建相同的内存配置,以便所有内存区域在进程之间共享,并且所有指向该内存的指针都是有效的,并且指向相同的处理对象。

2.开发模式

2.1对称/对等进程

DPDK多进程支持能够用于创建一系列对等进程来处理同样的工作负载。这个模式相当于多线程,每个线程有相同的主循环函数,这个已经在大量DPDK例子中使用。在这种模式下,通过--proc-type=primary 标记设置为主进程,用 --proc-type= secondary标记。

二. 例子演示

simple_mp 和 symmetric_mp例子说明:

dpdk运行环境,大页面,网卡igb绑定等。

step 1:

          cd /home/pangyemeng/dpdk-16.04/examples/multi_process/simple_mp

step 2 编译:

          make

step 3 运行:

主进程:./simple_mp -l 0-1 -n 4 --proc-type=primary

从进程:./simple_mp -l 0-1 -n 4 --proc-type=secondary

step 4 发送消息:

主进程发送 test:

从进程接收:

三. 源码

	//EAL 初始化
	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_exit(EXIT_FAILURE, "Cannot init EAL\n");
	/*根据--proc-type=primary来初始化
	 *  主进程是创建相关ring,mempool
	 *  从进程查找和创建相关消息
	 * */
 
	if (rte_eal_process_type() == RTE_PROC_PRIMARY){
		send_ring = rte_ring_create(_PRI_2_SEC, ring_size, rte_socket_id(), flags);
		recv_ring = rte_ring_create(_SEC_2_PRI, ring_size, rte_socket_id(), flags);
		message_pool = rte_mempool_create(_MSG_POOL, pool_size,
				string_size, pool_cache, priv_data_sz,
				NULL, NULL, NULL, NULL,
				rte_socket_id(), flags);
	} else {
		recv_ring = rte_ring_lookup(_PRI_2_SEC);
		send_ring = rte_ring_lookup(_SEC_2_PRI);
		message_pool = rte_mempool_lookup(_MSG_POOL);
	}
	if (send_ring == NULL)
		rte_exit(EXIT_FAILURE, "Problem getting sending ring\n");
	if (recv_ring == NULL)
		rte_exit(EXIT_FAILURE, "Problem getting receiving ring\n");
	if (message_pool == NULL)
		rte_exit(EXIT_FAILURE, "Problem getting message pool\n");
 
	RTE_LOG(INFO, APP, "Finished Process Init.\n");
 
	/* call lcore_recv() on every slave lcore */
	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
		rte_eal_remote_launch(lcore_recv, NULL, lcore_id);
	}
static int
lcore_recv(__attribute__((unused)) void *arg)
{
	unsigned lcore_id = rte_lcore_id();
 
	printf("Starting core %u\n", lcore_id);
	while (!quit){
		void *msg;
		//从环中提取消息
		if (rte_ring_dequeue(recv_ring, &msg) < 0){
			usleep(5);
			continue;
		}
		printf("core %u: Received '%s'\n", lcore_id, (char *)msg);
		//创建消息到内存池
		rte_mempool_put(message_pool, msg);
	}
 
	return 0;
}

四. 多进程限制

a.这个多进程特征需要同一块hugepage内存映射到当前所有应用。这linux安全特征-ASLR(随机内存布局,主要防止内存溢出)能够干涉映射,因此需要关闭这个特征来满足运行多进程应用。

b.所有的DPDK进程作为单独的应用,而且用共享内存,必须有不同的逻辑核参数。任何主进程和从进程或两个从进程不能使用任何同一个逻辑核。尝试使用将导致内存池cache破坏等问题。

c.例如 Ethernet设备的链路状态等中断,不会在从进程工作。所有的中断触发都仅仅在主进程。在多个进程中需要中断通知的任何应用程序都应该提供它自己的机制将中断信息从主进程转移到需要该信息的任何从进程。

d.在多个进程间使用基于不同编译二进制函数指针是不支持的,因为在一个进程中给点的函数位置在另一个进程中可能在不同的位置。这样可以防止librte_hash库在多线程实例中正常运行,因为它使用指向内部散列函数的指针。

要解决此问题,建议多进程应用程序通过直接从代码中调用散列函数,然后使用rte_hash_add_with_hash()/ rte_hash_lookup_with_hash()函数来执行哈希计算,而不是内部执行散列的函数,例如 作为rte_hash_add()/ rte_hash_lookup()。

e.根据所使用的硬件和所使用的DPDK进程的数量,可能无法在每个DPDK实例中都可以使用HPET定时器。 可用于Linux *用户空间的HPET比较器的最小数量可以只是一个比较器,这意味着只有第一个主DPDK流程实例可以打开和mmap / dev / hpet。 如果所需DPDK进程的数量超过可用的HPET比较器数量,则TSC(此版本中的默认计时器)必须用作所有进程而不是HPET的时间源。

原文链接:https://blog.csdn.net/pangyemeng/article/details/77678139

更多DPDK学习资料有需要的可以自行添加进入学习交流君 羊 793599096 免费获取,或自行报名学习,免费订阅,永久学习,关注我持续更新哦!!!

学习地址:http://ke.qq.com/course/5066203?flowToken=1043717

你可能感兴趣的:(网络,服务器,linux,网络协议,tcp/ip)