intel dpdk api interrupt module 中断模块介绍
声明:此文档只做学习交流使用,请勿用作其他商业用途
author:朝阳_tony
E-mail : linzhaolover@gmail.com
Create Date: 2013-7-12 11:46:21 Friday
Last Change: 2013-7-12 16:35:36 Friday
转载请注明出处:http://blog.csdn.net/linzhaolove
此文中源码可以去http://dpdk.org/dev 网页中下载;更多官方文档请访问http://dpdk.org
1、intel dpdk interrupt 模块的初始化
首先调用rte_eal_intr_init()函数去初始化中断;
1)、rte_eal_intr_init()函数详解
- /* init the global interrupt source head */
- TAILQ_INIT(&intr_sources);
首先初始化一个队列链表,intr_sources 是一个static struct rte_intr_source_list结构体,经过TAILQ_HEAD(rte_intr_source_list, rte_intr_source)初始化后的结构体
- TAILQ_HEAD(rte_intr_cb_list, rte_intr_callback);
- TAILQ_HEAD(rte_intr_source_list, rte_intr_source);
- struct rte_intr_callback {
- TAILQ_ENTRY(rte_intr_callback) next;
- rte_intr_callback_fn cb_fn; /**< callback address */
- void *cb_arg; /**< parameter for callback */
- };
- struct rte_intr_source {
- TAILQ_ENTRY(rte_intr_source) next;
- struct rte_intr_handle intr_handle; /**< interrupt handle */
- struct rte_intr_cb_list callbacks; /**< user callbacks */
- };
struct rte_intr_source 里面 包含一中断句柄,和一个中断回调函数链表;
- /**
- * create a pipe which will be waited by epoll and notified to
- * rebuild the wait list of epoll.
- */
- if (pipe(intr_pipe.pipefd) < 0)
去创建一个管道,用于epoll的消息通知;
- /* create the host thread to wait/handle the interrupt */
- ret = pthread_create(&intr_thread, NULL,
- eal_intr_thread_main, NULL);
创建中断管理线程,去等待响应处理中断;
2)、中断线程管理函数详解
eal_intr_thread_main()作为中断线程的管理函数;
- /* create epoll fd */
- int pfd = epoll_create(1);
创建epoll功能文件描述符;dpdk是通过epoll消息机制进行通信,然后再从pipe管道中读取消息,完成dpdk中断机制的中断注册;
- pipe_event.data.fd = intr_pipe.readfd;
- /**
- * add pipe fd into wait list, this pipe is used to
- * rebuild the wait list.
- */
- if (epoll_ctl(pfd, EPOLL_CTL_ADD, intr_pipe.readfd,
- &pipe_event) < 0) {
- rte_panic("Error adding fd to %d epoll_ctl, %s\n",
- intr_pipe.readfd, strerror(errno));
- }
将管道描述符赋值给epoll的结构体中;通过epoll_ctl去设置监控管道的读描述符intr_pipe.readfd;
- rte_spinlock_lock(&intr_lock);
- TAILQ_FOREACH(src, &intr_sources, next) {
- if (src->callbacks.tqh_first == NULL)
- continue; /* skip those with no callbacks */
- ev.events = EPOLLIN | EPOLLPRI;
- ev.data.fd = src->intr_handle.fd;
- /**
- * add all the uio device file descriptor
- * into wait list.
- */
- if (epoll_ctl(pfd, EPOLL_CTL_ADD,
- src->intr_handle.fd, &ev) < 0){
- rte_panic("Error adding fd %d epoll_ctl, %s\n",
- src->intr_handle.fd, strerror(errno));
- }
- else
- numfds++;
- }
- rte_spinlock_unlock(&intr_lock);
这一段code应该是在使用uio设备时候才会运行;需要uio去注册中断函数;也会将uio设备文件描述符添加进去;
uio设备是支持用户态驱动的一种linux内核机制,在采用uio后会在/dev目录下产生几个设备文件;
- # ls /dev/uio*
- /dev/uio0 /dev/uio1 /dev/uio2 /dev/uio3
dpdk 拥有自己的自旋锁
- rte_spinlock_lock(&intr_lock);
- rte_spinlock_unlock(&intr_lock);
- eal_intr_handle_interrupts(pfd, numfds);
通过上面这个函数去等待消息,读取中断注册信息;而 numfds这个参数是指,去等待几个描述符的消息 ;
eal_intr_handle_interrupts定义在dpdk/lib/librte_eal/linuxapp/eal/eal_interrupts.c文件中;
我们去看一下这函数的实现;
- nfds = epoll_wait(pfd, events, totalfds,
- EAL_INTR_EPOLL_WAIT_FOREVER);
此函数会调用epoll_wait去阻塞住,等待消息的到来;nfds是指消息到来的多少个;消息的内容是存储在events这个结构体数组中 ;
- /* epoll_wait has at least one fd ready to read */
- if (eal_intr_process_interrupts(events, nfds) < 0)
- return;
在eal_intr_handle_interrupts再去调用eal_intr_process_interrupts去出处理真正的消息;
介绍一下这个函数eal_intr_process_interrupts
- /**
- * if the pipe fd is ready to read, return out to
- * rebuild the wait list.
- */
- if (events[n].data.fd == intr_pipe.readfd){
她会判断是否是管道传过来的消息,如果是管道消息,要去返回重建链表;重建的是 epoll的wait 的等待链表;
一开始还没有中断注册,所以就直接注册了一个管道的epoll wait,后来了新的中断描述符注册,就需要重新建立一个epoll的等待列表;
- TAILQ_FOREACH(src, &intr_sources, next)
- if (src->intr_handle.fd ==
- events[n].data.fd)
- break;
判断是不是中断描述符中的消息;
如果是中断描述符的信息,接下来,将调用的回调函数,赋值给中断链表;
- /* for this source, make a copy of all the callbacks,
- * then unlock the lock, so the callbacks can
- * themselves manipulate the list for future
- * instances.
- */
- active_cb = 0;
- memset(active_cbs, 0, sizeof(active_cbs));
- TAILQ_FOREACH(cb, &src->callbacks, next)
- active_cbs[active_cb++] = *cb;
- /**
- * Finally, call all callbacks from the copy
- * we made earlier.
- */
- for (i = 0; i < active_cb; i++) {
- if (active_cbs[i].cb_fn == NULL)
- continue;
- active_cbs[i].cb_fn(&src->intr_handle,
- active_cbs[i].cb_arg);
- }
最后调用回调函数去进行中断处理;
2、中断模块的应用
1、首先应该初始中断模块
dpdk一般会在rte_eal_init()函数中调用rte_eal_intr_init()初始中断模块;
2、注册回调函数
- int rte_intr_callback_register(struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb, void *cb_arg)
struct rte_intr_handle *intr_handle 为中断函数句柄;
rte_intr_callback_fn cb 这个参数为中断回调函数指针;
void *cb_arg 这个参数是给回调函数传递参数的指针;
在./lib/librte_eal/linuxapp/eal/eal_alarm.c 文件的第160行,运用了这个函数
注册函数是在int rte_eal_alarm_set(uint64_t us, rte_eal_alarm_callback cb_fn, void *cb_arg) 函数中调用的;
- if (!handler_registered) {
- ret |= rte_intr_callback_register(&intr_handle,
- eal_alarm_callback, NULL);
- handler_registered = (ret == 0) ? 1 : 0;
- }
- static struct rte_intr_handle intr_handle = {.fd = -1 };
intr_handle 为alarm 在初始化时,定义初始化的一个全局的时钟中断句柄;
eal_alarm_callback 为alarm 定义的回调函数指针;
最后一个参数传递的为NULL ,应该是不传递任何参数;看了一下eal_alarm_callback 函数实现,的确没有用传递的参数,我们自己写程序时也要注意留接口,虽然当时不用,但可以为以后扩展使用;
intel dpdk api interrupt module 中断模块介绍的更多相关文章
- Python第五章__模块介绍,常用内置模块
Python第五章__模块介绍,常用内置模块 欢迎加入Linux_Python学习群 群号:478616847 目录: 模块与导入介绍 包的介绍 time &datetime模块 rando ...
- 大数据技术之_14_Oozie学习_Oozie 的简介+Oozie 的功能模块介绍+Oozie 的部署+Oozie 的使用案列
第1章 Oozie 的简介第2章 Oozie 的功能模块介绍2.1 模块2.2 常用节点第3章 Oozie 的部署3.1 部署 Hadoop(CDH版本的)3.1.1 解压缩 CDH 版本的 hado ...
- 简学Python第五章__模块介绍,常用内置模块
Python第五章__模块介绍,常用内置模块 欢迎加入Linux_Python学习群 群号:478616847 目录: 模块与导入介绍 包的介绍 time &datetime模块 rando ...
- 模块介绍/time/os...
本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configpars ...
- 一起来学习LiteOS中断模块的源代码
摘要:本文带领大家一起剖析了LiteOS中断模块的源代码. 本文我们来一起学习下LiteOS中断模块的源代码,文中所涉及的源代码,均可以在LiteOS开源站点https://gitee.com/Lit ...
- 嵌入式系统图形库GUI核心模块介绍
本文转载自:http://blog.csdn.net/xteda/article/details/6575278 (作者 冯青华 信庭嵌入式工作室(www.xteda.com)- CEO Blog:h ...
- IIS7 常用模块介绍说明
1.1.0 IIS常用的功能模块介绍: 1) 静态内容:可发布静态 Web 文件格式,比如 HTML 页面和图像文件. 2) 默认文档:允许您配置当用户未在 URL ...
- python模块介绍- multi-mechanize 性能测试工具
python模块介绍- multi-mechanize 性能测试工具 2013-09-13 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq 3739 ...
- python成长之路【第十八篇】:python模块介绍、模块导入和重载
一.模块和命名空间 一般来说,Python程序往往由多个模块文件构成,通过import语句连接在一起.每个模块文件是一个独立完备的变量包,即一个命名空间.一个模块文件不能看到其他文件定义的变量名,除非 ...
随机推荐
- jq bootstrap select 点击不能动弹
jq bootstrap select 点击不能动弹 因为是样式selectpicker 冲突. 解决办法换 样式 form-control <select name="ty ...
- python 面试题 删除字符串a中包含的字符串b
- Android 下拉刷新上拉载入 多种应用场景 超级大放送(上)
转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/47707017 关于Android下拉刷新上拉载入,网上的Demo太多太多了,这 ...
- 1. lvs+keepalived 高可用群集
一. keepalived 工具介绍 1.专为lvs 和HA 设计的一款健康检查工具 2.支持故障自动切换 3.支持节点健康状态检查 二. keepalived 实现原理剖析 keepalived ...
- vim对光标所在的数字进行增减
真是vim会在不经意间给你惊喜...... 现在发现把光标移到某数字的上方,c-a是加1, c-x是减1 当时真有点众里寻他千百度的感觉
- Hadoop生态优秀文章集锦
如何用形象的比喻描述大数据的技术生态?Hadoop.Hive.Spark 之间是什么关系? https://www.zhihu.com/question/27974418 HBase 和 Hive 的 ...
- iphone传感器
传感器 什么是传感器 传感器是一种感应\检测装置, 目前已经广泛应用于智能手机上 传感器的作用 用于感应\检测设备周边的信息 不同类型的传感器, 检测的信息也不一样 iPhone中的下面现象都是由传感 ...
- Data Decisions: DSP vs. DMP
http://www.cmo.com/features/articles/2016/3/9/data-decisions-dsp-vs-dmp.html As marketers assess the ...
- 在普通网页中如何调用html5+的plus对象
<script> //用法: HTML5+的plus对象,必须由click事件触发后,才能在普通网页中使用.所以在没有click的情况下,调用本文件可以解决问题! //在代码中使用: pl ...
- 【python】-- 类的继承(新式类/经典类)、多态
继承 之前我们说到了类的公有属性和类的私有属性,其实就是类的封装,现在准备随笔的 是继承,是面向对象的第二大特性. 面向对象编程 (OOP) 语言的一个主要功能就是“继承”.继承是指这样一种能力:它可 ...