声明:此文档只做学习交流使用,请勿用作其他商业用途

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()函数详解

  1. /* init the global interrupt source head */
  2. TAILQ_INIT(&intr_sources);

首先初始化一个队列链表,intr_sources 是一个static struct rte_intr_source_list结构体,经过TAILQ_HEAD(rte_intr_source_list, rte_intr_source)初始化后的结构体

  1. TAILQ_HEAD(rte_intr_cb_list, rte_intr_callback);
  2. TAILQ_HEAD(rte_intr_source_list, rte_intr_source);
  3. struct rte_intr_callback {
  4. TAILQ_ENTRY(rte_intr_callback) next;
  5. rte_intr_callback_fn cb_fn;  /**< callback address */
  6. void *cb_arg;                /**< parameter for callback */
  7. };
  8. struct rte_intr_source {
  9. TAILQ_ENTRY(rte_intr_source) next;
  10. struct rte_intr_handle intr_handle; /**< interrupt handle */
  11. struct rte_intr_cb_list callbacks;  /**< user callbacks */
  12. };

struct rte_intr_source 里面 包含一中断句柄,和一个中断回调函数链表;

  1. /**
  2. * create a pipe which will be waited by epoll and notified to
  3. * rebuild the wait list of epoll.
  4. */
  5. if (pipe(intr_pipe.pipefd) < 0)

去创建一个管道,用于epoll的消息通知;

  1. /* create the host thread to wait/handle the interrupt */
  2. ret = pthread_create(&intr_thread, NULL,
  3. eal_intr_thread_main, NULL);

创建中断管理线程,去等待响应处理中断;

2)、中断线程管理函数详解

eal_intr_thread_main()作为中断线程的管理函数;

  1. /* create epoll fd */
  2. int pfd = epoll_create(1);

创建epoll功能文件描述符;dpdk是通过epoll消息机制进行通信,然后再从pipe管道中读取消息,完成dpdk中断机制的中断注册;

  1. pipe_event.data.fd = intr_pipe.readfd;
  2. /**
  3. * add pipe fd into wait list, this pipe is used to
  4. * rebuild the wait list.
  5. */
  6. if (epoll_ctl(pfd, EPOLL_CTL_ADD, intr_pipe.readfd,
  7. &pipe_event) < 0) {
  8. rte_panic("Error adding fd to %d epoll_ctl, %s\n",
  9. intr_pipe.readfd, strerror(errno));
  10. }

将管道描述符赋值给epoll的结构体中;通过epoll_ctl去设置监控管道的读描述符intr_pipe.readfd;

  1. rte_spinlock_lock(&intr_lock);
  2. TAILQ_FOREACH(src, &intr_sources, next) {
  3. if (src->callbacks.tqh_first == NULL)
  4. continue; /* skip those with no callbacks */
  5. ev.events = EPOLLIN | EPOLLPRI;
  6. ev.data.fd = src->intr_handle.fd;
  7. /**
  8. * add all the uio device file descriptor
  9. * into wait list.
  10. */
  11. if (epoll_ctl(pfd, EPOLL_CTL_ADD,
  12. src->intr_handle.fd, &ev) < 0){
  13. rte_panic("Error adding fd %d epoll_ctl, %s\n",
  14. src->intr_handle.fd, strerror(errno));
  15. }
  16. else
  17. numfds++;
  18. }
  19. rte_spinlock_unlock(&intr_lock);

这一段code应该是在使用uio设备时候才会运行;需要uio去注册中断函数;也会将uio设备文件描述符添加进去;

uio设备是支持用户态驱动的一种linux内核机制,在采用uio后会在/dev目录下产生几个设备文件;

  1. # ls /dev/uio*
  2. /dev/uio0  /dev/uio1  /dev/uio2  /dev/uio3

dpdk 拥有自己的自旋锁

  1. rte_spinlock_lock(&intr_lock);
  2. rte_spinlock_unlock(&intr_lock);
  1. eal_intr_handle_interrupts(pfd, numfds);

通过上面这个函数去等待消息,读取中断注册信息;而 numfds这个参数是指,去等待几个描述符的消息 ;

eal_intr_handle_interrupts定义在dpdk/lib/librte_eal/linuxapp/eal/eal_interrupts.c文件中;

我们去看一下这函数的实现;

  1. nfds = epoll_wait(pfd, events, totalfds,
  2. EAL_INTR_EPOLL_WAIT_FOREVER);

此函数会调用epoll_wait去阻塞住,等待消息的到来;nfds是指消息到来的多少个;消息的内容是存储在events这个结构体数组中 ;

  1. /* epoll_wait has at least one fd ready to read */
  2. if (eal_intr_process_interrupts(events, nfds) < 0)
  3. return;

在eal_intr_handle_interrupts再去调用eal_intr_process_interrupts去出处理真正的消息;

介绍一下这个函数eal_intr_process_interrupts

  1. /**
  2. * if the pipe fd is ready to read, return out to
  3. * rebuild the wait list.
  4. */
  5. if (events[n].data.fd == intr_pipe.readfd){

她会判断是否是管道传过来的消息,如果是管道消息,要去返回重建链表;重建的是   epoll的wait 的等待链表;

一开始还没有中断注册,所以就直接注册了一个管道的epoll wait,后来了新的中断描述符注册,就需要重新建立一个epoll的等待列表;

  1. TAILQ_FOREACH(src, &intr_sources, next)
  2. if (src->intr_handle.fd ==
  3. events[n].data.fd)
  4. break;

判断是不是中断描述符中的消息;

如果是中断描述符的信息,接下来,将调用的回调函数,赋值给中断链表;

  1. /* for this source, make a copy of all the callbacks,
  2. * then unlock the lock, so the callbacks can
  3. * themselves manipulate the list for future
  4. * instances.
  5. */
  6. active_cb = 0;
  7. memset(active_cbs, 0, sizeof(active_cbs));
  8. TAILQ_FOREACH(cb, &src->callbacks, next)
  9. active_cbs[active_cb++] = *cb;
  1. /**
  2. * Finally, call all callbacks from the copy
  3. * we made earlier.
  4. */
  5. for (i = 0; i < active_cb; i++) {
  6. if (active_cbs[i].cb_fn == NULL)
  7. continue;
  8. active_cbs[i].cb_fn(&src->intr_handle,
  9. active_cbs[i].cb_arg);
  10. }

最后调用回调函数去进行中断处理;

2、中断模块的应用

1、首先应该初始中断模块

dpdk一般会在rte_eal_init()函数中调用rte_eal_intr_init()初始中断模块;

2、注册回调函数

  1. 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) 函数中调用的;

  1. if (!handler_registered) {
  2. ret |= rte_intr_callback_register(&intr_handle,
  3. eal_alarm_callback, NULL);
  4. handler_registered = (ret == 0) ? 1 : 0;
  5. }
  1. 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 中断模块介绍的更多相关文章

  1. Python第五章__模块介绍,常用内置模块

    Python第五章__模块介绍,常用内置模块 欢迎加入Linux_Python学习群  群号:478616847 目录: 模块与导入介绍 包的介绍 time &datetime模块 rando ...

  2. 大数据技术之_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 ...

  3. 简学Python第五章__模块介绍,常用内置模块

    Python第五章__模块介绍,常用内置模块 欢迎加入Linux_Python学习群  群号:478616847 目录: 模块与导入介绍 包的介绍 time &datetime模块 rando ...

  4. 模块介绍/time/os...

    本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configpars ...

  5. 一起来学习LiteOS中断模块的源代码

    摘要:本文带领大家一起剖析了LiteOS中断模块的源代码. 本文我们来一起学习下LiteOS中断模块的源代码,文中所涉及的源代码,均可以在LiteOS开源站点https://gitee.com/Lit ...

  6. 嵌入式系统图形库GUI核心模块介绍

    本文转载自:http://blog.csdn.net/xteda/article/details/6575278 (作者 冯青华 信庭嵌入式工作室(www.xteda.com)- CEO Blog:h ...

  7. IIS7 常用模块介绍说明

    1.1.0   IIS常用的功能模块介绍: 1)         静态内容:可发布静态 Web 文件格式,比如 HTML 页面和图像文件. 2)         默认文档:允许您配置当用户未在 URL ...

  8. python模块介绍- multi-mechanize 性能测试工具

    python模块介绍- multi-mechanize 性能测试工具 2013-09-13 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq 3739 ...

  9. python成长之路【第十八篇】:python模块介绍、模块导入和重载

    一.模块和命名空间 一般来说,Python程序往往由多个模块文件构成,通过import语句连接在一起.每个模块文件是一个独立完备的变量包,即一个命名空间.一个模块文件不能看到其他文件定义的变量名,除非 ...

随机推荐

  1. Matlab中使用jython扩展功能

    Matlab中面向对象能力并不强,通过使用jython引擎能够对其功能扩展. 1 编辑classpath.txt增加jython.jar 在matlab中输入 which classpath.txt ...

  2. linux的用户、群组

    1.      用户及passwd文件 1)      掌握/etc/passwd文件的功能:存储所有用户的相关信息,该文件也被称为用户信息数据库(Database). 2)      /etc/pa ...

  3. jquery的find()

    jQuery 遍历 - find() 方法 jQuery 遍历参考手册 实例 搜索所有段落中的后代 span 元素,并将其颜色设置为红色: $("p").find("sp ...

  4. 第3章 如何编写函数定义 3.7 if特殊表

    这部分来学习下if特殊表,之前学了defun和let,不好意思,博客中没有写但是鄙人已经看了,哈哈. 什么是if表 if条件特殊表是为了让计算机对条件加以判断,然后选择不同的执行路径的. if特殊表的 ...

  5. Android Studio 2.0 稳定版新特性介绍

    Android Studio 2.0 最终迎来了稳定版本号,喜大普奔. 以下这篇文章是2.0新特性的一些简介. 假设想看具体内容请看这里<Android Studio有用指南> 文章转自这 ...

  6. HDU 5901 Count primes (2016 acm 沈阳网络赛)

    原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5901 题意:输入n,输出n以内质数个数 模板题,模板我看不懂,只是存代码用. 官方题解链接:https ...

  7. Mysql的学习研究

    2017年5月16日11:26:17 从今天开始过一遍数据库的基础教程,加油!!!!! 看了之后对一些基础知识有了理解,加油... 笔记: 2017年5月16日11:35:46mysql的基础教程1. ...

  8. android shape的用法总结

    参考代码: <shape xmlns:android="http://schemas.android.com/apk/res/android" > <corner ...

  9. python 上传文件下载图片

    python 2.7 poster-0.8.1 requests-2.7.0 #coding:utf-8import urllibimport urllib2import sysimport time ...

  10. 一篇文章彻底弄清ARC始末

    本文转载至 http://blog.csdn.net/allison162004/article/details/38758265 自动引用计数(ARC)是编译器的一个特色,提供了Objective- ...