DPU网络开发SDK—DPDK(四)

news/2024/11/29 2:47:19/

rte_eal_init()

接上次内容继续对rte_eal_init()所做的工作进行分析。

12. 初始化配置

rte_config_init()中,会根据process_type进行不同的初始化任务。process_type是由eal的启动参数指定的,目前支持两种模式:primary和secondary。process_type在解析参数时存放在internal_config中,然后此处赋值到rte_config中。

  • 按照primary方式启动

DPDK在解析参数的时候,会初始化一个runtime_dir全局变量。如果没有特殊配置,这个目录为/var/run/dpdk/rte,DPDK会基于此目录中的文件实现一些进程间通信。

primary方式启动时,会调用rte_eal_config_create(),该过程在runtime_dir中创建一个名称为config的文件,将文件大小截断为rte_mem_config的大小,并添加一个文件锁。文件锁类型为struct flock,这种锁可以指定文件的哪些数据片段需要被保护。在此处保护的是整个文件,也就是整个rte_mem_config。

接下来需要将该文件映射到DPDK进程的虚拟空间当中,调用mmap()进行此操作,映射之后可读可写,且其他进程同样可以映射该文件到其虚拟空间当中。在映射之前,会确定映射到进程的具体哪个虚拟地址上,该过程由eal_get_virtual_area()实现。

eal_get_virtual_area()会基于internal_config中的base_virtaddr确定目标映射地址(该值默认为0,可通过启动参数修改之)。在base_virtaddr的基础上,以系统的page_size为递增单位,依次检查某个映射地址是否满足映射要求,直到找个第一个满足要求的映射地址为止。

完成对config文件的映射之后,将rte_config中的rte_mem_config拷贝到映射好的虚拟地址空间,并将rte_config中rte_mem_config的指针指向此空间,后续对rte_mem_config的修改就可以直接反馈到config文件当中了。

  • 按照secondary方式启动

如果是secondary启动DPDK进程,则直接打开primary进程创建的config文件并mmap()到secondary进程中,后将rte_config中rte_mem_config的指针指向此空间。如此secondary进程看到的rte_mem_config看到的内容和primary进程看到的是一样的,两者在mem配置方面实现了进程间的通信,且primary进程在创建config文件的过程中为其设置了锁,使得对其的写操作是互斥的,避免了两个进程之间的竞争问题。

13. 初始化信号处理

此处启动一个线程eal_intr_thread_main(),该线程中无限循环执行如下的过程:

  • 创建一个epoll,并将中断信号传递管道中读信号的一侧的文件描述符intr_pipe.readfp添加到epoll中进行监听。

  • 将intr模块的全局变量intr_sources列表中的所有文件描述符添加到epoll中进行监听。

  • 无限循环等待epoll中的文件描述符的事件的发生,并依次处理发生的事件。

  • 关闭epoll。

14. 创建一个定时器

此处调用Linux的系统函数timerfd_create()创建一个定时器的文件描述符,并将其存在alarm模块的全局变量intr_handle中。在后续的操作中,intr_handle会注册到前面提到的intr_sources列表中。

15. 初始化进程间通信文件

rte_mp_channel_init()在/var/run/dpdk/rte目录下生成一个文件,名称为mp_socket_*。调用open_socket_id创建UDP类型的socket,保存于全局变量mp_fd中,并调用bind将mp_fd与通信文件进行绑定。如果进程是primary,那么通信文件为/var/run/dpdk/rte/mp_socket,如果是secondary,通信文件为/var/run/dpdk/rte/mp_socket_${pid}_${timestamp}。然后重启一个线程,线程处理函数为mp_handle(),该处理函数无限循环接收mp_fd代表的socket发来的信息并处理之。该进程间通信文件的是primary和secondary进程之间的通信,secondary进程之间是没有通信需求的。

16. 设备热插拔初始化

eal_mp_dev_hotplug_init()中,如果当前进程是primary,则会注册一个回调函数handle_secondary_request()用于处理处理来自secondary进程的设备热插拔请求。反之secondary进程中会注册handle_primary_request()函数,

17. 各总线遍历设备

bus模块全局变量rte_bus_list存储了所有的总线的列表,此处依次遍历每个总线并调用总线的scan()方法。

在DPDK中存在一个描述总线的结构struct rte_bus,该结构中定义了一些总线的接口函数,scan()就是其中之一。对于总线来说,scan()方法的主要作用是用来遍历所有的设备,并将设备与注册在该总线上的驱动进行匹配,当匹配成功时,建立驱动和设备之间的对应关系。DPDK只提供了接口要求各总线实现该接口,具体如何实现则由各总线设备自行定义。

总线通过注册的方式注册到rte_bus_list当中,目前DPDK支持的总线有:

  • vmbus

  • vdev

  • pci

  • fpga

  • fslmc

  • dpaa

struct rte_bus的结构如下,除了scan()方法,还有probe(),find_device()等。

struct rte_bus {TAILQ_ENTRY(rte_bus) next;   //在rte_bus_list中的入口const char *name;            //总线名称rte_bus_scan_t scan;         //遍历总线上挂载的设备rte_bus_probe_t probe;       //探测总线上挂载的设备rte_bus_find_device_t find_device; //查找总线上挂载的设备rte_bus_plug_t plug;         //建立某个设备和驱动的联系rte_bus_unplug_t unplug;     //接触某个设备和驱动的联系rte_bus_parse_t parse;       //解析设备名称rte_dev_dma_map_t dma_map;   //设备映射到DMPrte_dev_dma_unmap_t dma_unmap; //解除设备到DMA的映射struct rte_bus_conf conf;    //总线配置rte_bus_get_iommu_class_t get_iommu_class; //iommu类别rte_dev_iterate_t dev_iterate; //设备迭代rte_bus_hot_unplug_handler_t hot_unplug_handler;  //处理热拔出设备失败rte_bus_sigbus_handler_t sigbus_handler;  //处理sigbus错误
};

rte_bus的实现是仿照了Linux内核中总线的角色,主要是为了建立设备和驱动之间的联系,后期我们会以某个总线设备为例查看这些接口方法的具体实现。

未完待续…


http://www.ppmy.cn/news/18591.html

相关文章

【Mongoose笔记】TCP 客户端与服务器

【Mongoose笔记】TCP 客户端与服务器 简介 Mongoose 笔记系列用于记录学习 Mongoose 的一些内容。 Mongoose 是一个 C/C 的网络库。它为 TCP、UDP、HTTP、WebSocket、MQTT 实现了事件驱动的、非阻塞的 API。 项目地址: https://github.com/cesanta/mongoose学习…

Python版本PathPlanning运动规划库中RotationToWorldFrame函数内部计算过程分析

本文主要对Python版本PathPlanning运动规划库中RotationToWorldFrame函数的内部计算过程分析,包括相关必备python基础和计算过程分析两部分,并给出了等效的MATLAB版本计算过程程序,方便分析对比。 (注:RotationToWorld…

模拟实现一个简单的命令行解释器(shell)

目录 前言 环境变量与本地变量 和环境变量相关的命令 获取环境变量的三种方法 第一种 第二种 第三种 进程地址空间 页表 为什么存在进程地址空间 第一 第二 第三 进程控制 进程的产生 进程终止 进程等待 进程替换 模拟实现一个shell 前言 我们通过各种指令来实现…

Java 23种设计模式(2.创建者模式-单例设计模式)

1. 创建者模式 创建型模式分为: 单例模式工厂方法模式抽象工程模式原型模式建造者模式 什么是创建者模式? 创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。 这样可以降低系统的耦合度…

CSDN竞赛24期题解

总结 本次竞赛的主要考点在于模拟,而且需要考虑的情况还蛮多,平时复杂点的模拟很少做,这次AC也花了挺长时间,后面还是需要夯实一下基础啊。 题目列表 1.计数问题 题目描述 试计算在区间 1 到 n 的所有整数中,数字…

【Linux_】环境变量

【Linux_】环境变量 心有所向,日复一日,必有精进专栏:《Linux_》作者:沂沐沐目录 【Linux_】环境变量 什么是环境变量 常见变量 查看环境变量方法 环境变量相关的命令 通过系统调用获取或设置环境变量 环境变量通常是具有全…

LeetCode 1802. 有界数组中指定下标处的最大值(C++)

思路: 首先根据题目要求,相邻数字的差距不能大于1,所以数组中的元素分布一定是以最大元素位置为塔顶,向两边发散的金字塔状,最小值为1,这样的结构能保证数组元素和一定是最小的(只有1是重复元素…

Allegro如何输出第三方网表操作指导

Allegro如何输出第三方网表操作指导 在做PCB设计的时候,会需要输第三方网表,Allegro支持快速输出第三方网表,如下图 具体操作如下 选择File选择Export