二、DPDK代码——初始化入口(1)

转载请注明出处,谢谢。

初始化入口函数eal_init():

/* Launch threads, called at application init(). */

int

rte_eal_init(int argc, char **argv)

{

    int i, fctret, ret;

    pthread_t thread_id;

    static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);

    const char *p;

    static char logid[PATH_MAX];

***//初始化定义了私有的rte_config结构,包括了内存rte_mem_config结构

const struct rte_config *config = rte_eal_get_configuration();//这里从公共config结构

struct internal_config *internal_conf =eal_get_internal_configuration();//获取私有config结构

    //检测cpu的标识是否支持dpdk在进行cpu运行时,会考虑采用cpu高级指令来优化运算速度。

rte_cpu_is_supported()

rte_cpu_is_supported()这里循环验证每个核心是否支持特性,特性在构建系统时就已经生成,同时也在生成的特性表中加入dpdk默认所需要的特性。

->rte_cpu_get_flag_enabled()获取特性比较后使能。对于新的指令集特性需要用新的编译器编译,否则会导致失败。

 

rte_config_init() 

rte_config_init()根据主从进程分->rte_eal_config_create()

                                                             对internal->base_virtaddr->为0则已经对齐

                                                                                                          ->不为0 按照page_sz对齐,否则直接映射造成a page 的浪费。然后对修改映射文件大小,调整映射文件属性。保存内存空间。最后进行按照page_sz对齐mmap。此时的地址是mem_config的起始地址。

                                                     ->rte_eal_config_attach()

                                                             尝试打开映射文件,打开成功进行mmap

 

rte_eal_intr_init() 

         属于设备中断非数据中断,创建的子线程优先级较高。

         对于DPDK进程,一般有一个控制中断线程和多个轮询线程。

rte_eal_intr_init接口用于中断的初始化,内部会创建一个读写管道,用来控制是否退出epoll机制。当应用层添加了新的中断源或者卸载了中断源, 在上面提到的两个注册与卸载函数里面,会往管道写入数据,此时epoll读管道事件将会被触发,读取这个管道的内容后,从epoll中退出后,将新加的中断源注册到epoll, 或者将卸载的中断源从epoll移除。这些操作都是在子线程中完成的,由子线程来处理中断事件,主线程则处理报文的高速转发。

eal_intr_thread_main是中断子线程的入口函数,内部会创建一个epoll句柄,并将管道描述符, 中断源链表中的所有描述符都加入到epoll事件机制中。需要注意的是这个子线程是一个死循环,永远都不会退出。如果有新的中断源加入或者移除,则会关闭epoll句柄,然后重新创建epoll对象,重新将管道以及中断源链表中的描述符加入到epoll中,这是一个循环的过程。一句话:这个死循环是为了在有新的中断源加入或者移除时,能够重复创建epoll句柄以及将中断源加入到epoll。   在将管道描述符,中断源链表中的所有描述符注册到epoll红黑树后,eal_intr_handle_interrupts内部会调用epoll_wait等待中断事件,管道事件的触发,这是一个异步的过程。需要注意的是这也是一个死循环,什么时候会退出呢? 还是上面提到的,在有新的中断源加入或者移除,会退出这个这个死循环。想想如果没有这个for死循环会发生什么事件呢?相当于每次epol_wait返回后,都需要关闭epoll句柄,重新创建epoll句柄,然后重新将管道以及中断源链表中的所有描述符加入到epoll中,这些系统调用也是要消耗性能的,只有在新加入中断源或者移除中断源时才需要这么做。如果都没有新加或者移除的中断源就没有必要这么做了。一句话:这个死循环是为了等待中断以及管道事件触发。    当epoll_wait返回后,说明有中断事件发生或者管道事件的发生,此时调用eal_intr_process_interrupts开始处理已经发生的事件。如果是管道事件,则直接退出epoll事件循环,这是优先级最高的事件。如果是中断源事件,则查找到相应的中断源,然后调用这个中断源注册的所有中断回调

dpdk自己实现了一个中断机制,例如定时器中断,uio中断。这个中断是应用层中断, 而不是像linux内核实现的硬件中断; 且dpdk实现的中断机制属于控制中断,用来实现一些控制操作,例如uio中断用来设置一些网卡的状态之类。网卡收发包过程,还是使用轮询的方式从网卡接收报文.

      dpdk实现了uio, 定时器alarm, vfio三种中断,且用链表来管理这些中断源。当应用层需要设置中断时, 设置好中断的触发回调后就可以调用rte_intr_callback_register接口注册一个中断源到中断链表中; 当应用层想取消某个中断源时,调用rte_intr_callback_unregister接口从中断源链表中移除一个中断源。内部会将中断源链表中的所有中断源描述符都加入到epoll实现的红黑树中, 当相应中断源有事件发生时,epoll会调用这些中断源注册的回调函数。

certe_mp_channel_init()

运行中产生:

Path = /var/run/dpdk/rte

/my_socket_*

My_filter=/var/run/dpdk/rt

My_dir_path=mp_socket_*

rte_mp_channel_init()

(1)生成进程间通信共享文件过滤变量mp_filter,值为” mp_socket_* “。

(2)生成进程间通信共享文件所在的目录mp_dir_path,值为”/var/run/dpdk/rte”。

(3)调用open_socket_fd()函数创建SOCK_DGRAM类型的socket, 保存在全局变量mp_fd中,并用bind()函数将mp_fd 与通信文件进行绑定。

如果是主进程,则通信文件为:

/var/run/dpdk/rte/mp_socket

如果是次进程,则通信文件为:

/var/run/dpdk/rte/mp_socket_<pid>_<rdtsc>

如果是次进程,则根据通信文件/var/run/dpdk/rte/mp_socket 向主进程发送消息,

而主进程通过通信文件

/var/run/dpdk/rte/mp_socket_<pid>_<rdtsc>

向所有次进程发送消息。

次进程之间没有消息通信。

(4)创建消息处理线程,线程名为”rte_mp_handle”,线程处理函数为mp_handle()函数

消息读取函数read_msg()

该函数是对recvmsg()函数的封装,该函数对消息传递的各项结构进行赋值与封装,

函数也会得到struct sockaddr_un 结构的通信沟通文件路径。

之后将接收到的消息赋值到msg中,并由process_msg()函数处理。

消息处理函数process_msg()

该函数用来处理接收到的消息。

(1)函数首先判断消息的类型,如果是响应的消息MP_REP,或要求忽略的消息MP_IGN,

则去pending列表pending_requests中查找被挂起的消息,根据消息类型对消息做同步或异步处理。

(2)之后,根据消息的msg->name,即地址,从action_entry_list列表中查找对应的entry。

如果没有找到,则判断如果消息是一个请求消息,且DPDK初始化还没有完成,则发送一个空消息,告诉请求者忽略当前进程的存在。

如果找到了,就调用对应的消息处理回调函数,对消息做对应的处理。

rte_bus_scan()

rte_bus_scan是bus scan提供的主接口,内部会调用所有bus->scan。接口的目的是循环扫描所有bus下注册的设备。

rte_bus_scan->bus.scan->bus.rte_pci_scan()(pci_common.c定义)

其中bus.scan到rte_pci_scan在编译的时候通过RTE_REGISTER_BUS就已经完成注册了。

    

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值