intel dpdk api interrupt module 中断模块介绍

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

author:朝阳_tony
E-mail : [email protected]
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()函数详解

[cpp] view plain copy

print?

  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)初始化后的结构体

[cpp] view plain copy

print?

  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 里面 包含一中断句柄,和一个中断回调函数链表;

[cpp] view plain copy

print?

  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的消息通知;

[cpp] view plain copy

print?

  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()作为中断线程的管理函数;

[cpp] view plain copy

print?

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

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

[cpp] view plain copy

print?

  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;

[cpp] view plain copy

print?

  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目录下产生几个设备文件;

[plain] view plain copy

print?

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

dpdk 拥有自己的自旋锁

[cpp] view plain copy

print?

  1. rte_spinlock_lock(&intr_lock);
  2. rte_spinlock_unlock(&intr_lock);

[cpp] view plain copy

print?

  1. eal_intr_handle_interrupts(pfd, numfds);

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

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

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

[cpp] view plain copy

print?

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

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

[cpp] view plain copy

print?

  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

[cpp] view plain copy

print?

  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的等待列表;

[cpp] view plain copy

print?

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

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

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

[cpp] view plain copy

print?

  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;

[cpp] view plain copy

print?

  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、注册回调函数

[cpp] view plain copy

print?

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

[cpp] view plain copy

print?

  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. }

[cpp] view plain copy

print?

  1. static struct rte_intr_handle intr_handle = {.fd = -1 };

intr_handle 为alarm 在初始化时,定义初始化的一个全局的时钟中断句柄;

eal_alarm_callback 为alarm 定义的回调函数指针;

最后一个参数传递的为NULL ,应该是不传递任何参数;看了一下eal_alarm_callback 函数实现,的确没有用传递的参数,我们自己写程序时也要注意留接口,虽然当时不用,但可以为以后扩展使用;

时间: 2024-11-06 09:13:18

intel dpdk api interrupt module 中断模块介绍的相关文章

8.模块介绍 time &amp;datetime模块 random os sys shutil json &amp; picle shelve xml处理 yaml处理 configparser hashlib subprocess logging模块 re正则表达式

本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configparser hashlib subprocess logging模块 re正则表达式 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.p

Ansible的安装、配置及常用模块介绍

Ansible的安装.配置及常用模块介绍 ansible安装方式 1. ansible安装常用两种方式,yum安装和pip程序安装 这里提供二种安装方式,任选一种即可: 1.使用yum安装 yum install epel-release -y yum install ansible –y 2. 使用pip(python的包管理模块)安装 pip install ansible   #如果没pip,需先安装pip.yum可直接安装: yum install python-pip pip inst

第三百二十四节,web爬虫,scrapy模块介绍与使用

第三百二十四节,web爬虫,scrapy模块介绍与使用 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫.Scrapy用途广泛,可以用于数据挖掘.监测和自动化测试. Scrapy 使用了 Twisted异步网络库来处理网络通讯.

IIS7 常用模块介绍说明

1.1.0   IIS常用的功能模块介绍: 1)         静态内容:可发布静态 Web 文件格式,比如 HTML 页面和图像文件. 2)         默认文档:允许您配置当用户未在 URL 中指定文件时供 Web 服务器返回的默认文件. 3)         目录浏览:允许用户查看 Web 服务器上的目录的内容.当用户未在 URL 中指定文件以及禁用或未配置默认文档时,使用“目录浏览”在目录中提供自动生成的所有目录和文件的列表.建议将该功能禁用. 4)         HTTP错误:

1Python标准库系列之模块介绍

Python标准库系列之模块介绍 Python的模块其实就是封装了一个或者多个功能的代码集合,以便于重用,模块可以是一个文件也可以是一个目录,目录的形式称作包. 模块分类 内置模块 内置模块可以理解成当你安装好python环境之后,直接可以使用import导入的就是内置模块,默认模块路径为:C:\Python35\lib,你也可以通过以下方式获取内置模块的路径:  # 导入sys模块  >>> import sys  # 最后一个目录就是内置模块的路径  >>> for

《JavaScript设计模式》深入学习 —— Module(模块)模式

模块是任何强大因工程需架构中不可或缺的一部分,它通常能够帮助我们清晰地分离和组织项目中的代码单元. (1) 对象字面量 var myObject = { variableKey : 'variableValue', functionkey : function () { // ... } }; 对象字面量不需要用new运算符来进行实例化,但不能用在一个语句的开头,因为开始可能被解读为一个块的开始.在对象的外部,新成员可以使用如下赋值语句来添加到对象字面量上: myObject.array = '

opencv模块介绍

opencv主要模块介绍: [calib3d]——其实就是就是Calibration(校准)加3D这两个词的组合缩写.这个模块主要是相机校准和三维重建相关的内容.基本的多视角几何算法,单个立体摄像头标定,物体姿态估计,立体相似性算法,3D信息的重建等等.[contrib]——也就是Contributed/Experimental Stuf的缩写, 该模块包含了一些最近添加的不太稳定的可选功能,不用去多管.2.4.8里的这个模块有新型人脸识别,立体匹配,人工视网膜模型等技术. [core]——核心

Ansible 常用模块介绍

ansible提供了众多模块,我们可以在ansible主机上运行ansible-doc -l命令查看ansible所有支持的模块.通过ansible-doc -s MODULE_NAME  命令可以查看指定模块的所有参数 查看所有模块 [email protected]:/etc/ansible/roles/tomcat8_install/tasks# ansible-doc  -l less 436 Copyright (C) 1984-2009 Mark Nudelman less come

Ansible 自动化运维工具之inventory和常用模块介绍

一.inventory介绍 前面我们介绍过ansible的hosts文件是存放被管理主机的,被管理主机比较少的情况下,直接在hosts中定义即可,但是以后很定会管理多台主机,而ansible可管理的主机集合就叫做inventory.在ansible中,描述你主机的默认方法是将它们列在一个文本文件中,这个文件叫inventory文件. 一个简单的inventory文件可能只包含一组主机名的列表,如下: ftp.testansible.com samba.testansible.com mail.t