DPDK源码分析之hello_world

hello_world涉及的知识点

  1. 这个示例实现的功能是什么?

主要就是检查eal环境抽象初始化是否成功,其中rte_eal_init会根据指定核数创建从线程,以及对应的线程loop函数。

2 .DPDK主从线程如何通信?

利用进程通信机制的pipe管道,本质是一个内核维护的环形缓冲队列,大小为get_free_page返回的一页内存。

管道为半双工的,因此,只能固定一方写一方读,从管道读取过的数据就无法再次被读了。

让我们看看linux-0.11是如何实现pipe的:

int pipe(int pipefd[2]);

每个进程最多可以打开文件数为NR_OPEN,首先遍历该进程未使用的文件句柄,找到可用的两个句柄,那么fd[0]和fd[1]返回的就是filp数组的下标。

接着遍历全局可用的文件描述符,找到可用的两个,接着在全局inode表中找到一个可用的inode节点,然后将两个文件描述符的inode指针都指向它。

通过inode获取硬盘逻辑缓存区,具体由super_block和inode idx获取缓存区buffer,然后将inode信息写入。

inode->isize = 一页内存的首地址,即后续环形管道的首地址。

让我们利用pipe写一个简单的进程通信示例

//父进程给子进程发送msg
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
 
int main(void)
{
    pid_t pid;
    char buf[1024];
    int fd[2];
    pipe(fd);

    char *p = "test for pipe\n";
   
   pid = fork();
   if (pid < 0) {
        printf("fork err\n", buf);
   } else if (pid == 0) {
        close(fd[1]);
        int len = read(fd[0], buf, sizeof(buf));
        printf("we get father msg:%s\n", buf);
        close(fd[0]);
   } else {
       close(fd[0]);
       write(fd[1], p, strlen(p));
       wait(NULL);
       close(fd[1]);
   }
    
    return 0;
}

无情gdb

rte_eal_init后会启动若干个线程,个数与硬件核数或配置核数有关,每个子线程都有各自的与主线程通信的pipe管道,这个管道的作用是:当主线程想要分配某一个函数让子线程执行时,主线程会通过pipe发送消息(1个字节,内容无所谓),子线程读取到这个消息后会回送给主线程一个消息,然后子进程便开始执行主线程赋值的函数(lcore_hello),而主线程收到子线程的回信后,就可以去给其他的线程分配函数了。

至此,各个子线程死循环执行线程函数eal_thread_loop,不断执行主线程分配的函数。

rte_eal_remote_launch中,主线程为指定的子线程赋值其功能函数:

static int
lcore_hello(__rte_unused void *arg)
{
	unsigned lcore_id;
	lcore_id = rte_lcore_id();
	printf("hello from core %u\n", lcore_id);
	return 0;
}

lcore_config[worker_id].f = lcore_hello;
lcore_config[worker_id].arg = arg;

然后主线程会往该子线程的pipe中写一个1字节的内容,接着会while等待子线程是否分配好了执行函数,具体的执行过程以及何时结束主线程不关心。

eal_thread_loop中,子线程循环读取pipe,当读到一个字节的时候,这意味着主线程已经分配给我了一个函数任务,那么我写入pipe一个字节告诉主线程我知道了,这就开始干活,并把自己的状态置为RUNNING,函数执行完毕后再置为FINISHED

/* call the function and store the return value */
fct_arg = lcore_config[lcore_id].arg;
ret = lcore_config[lcore_id].f(fct_arg);
lcore_config[lcore_id].ret = ret;

下面是我通过set scheduler-locking on捕获的一次完整的主从线程通信:

Reference

(27条消息) dpdk-16.04 eal lcore 多线程机制分析_龙瑜的博客-CSDN博客

(27条消息) dpdk之CPU绑定_liyu123__的博客-CSDN博客_dpdk绑核

(27条消息) dpdk_lcore_note_DPDK_lcore_学习笔记_Andrew Yang's Note-CSDN博客

(1条消息) linux管道pipe详解_oguro的博客-CSDN博客_管道

(1条消息) 理解inode_zhanshenyn的专栏-CSDN博客

NR_OPEN 与 NR_FILE 的区别-阿里云开发者社区 (aliyun.com)

(1条消息) 超级块 i节点 数据块 目录块 间接块_ymangu的专栏-CSDN博客_间接块

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于顾而言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值