一、中断注册方法

在linux内核中用于申请中断的函数是request_irq(),函数原型在Kernel/irq/manage.c中定义:

int request_irq(unsigned int irq, irq_handler_t handler,
                         unsigned long irqflags, const char *devname, void *dev_id)

irq是要申请的硬件中断号

handler是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。

irqflags是中断处理的属性,若设置了IRQF_DISABLED (老版本中的SA_INTERRUPT,本版zhon已经不支持了),则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了IRQF_SHARED (老版本中的SA_SHIRQ),则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM(老版本中的SA_SAMPLE_RANDOM),表示对系统熵有贡献,对系统获取随机数有好处。(这几个flag是可以通过或的方式同时使用的)

devname设置中断名称,通常是设备驱动程序的名称  在cat /proc/interrupts中可以看到此名称

dev_id在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。

request_irq()返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。

==================================================================================================================================

request_irq() | 注册中断服务

 
 
在 2.4 内核和 2.6内核中都使用 request_irq() 函数来注册中断服务函数。在 2.4 内核中,需要包含的头文件是 #include <linux/sched.h> ,2.6 内核中需要包含的头文件则是
#include <linux/interrupt.h> 。函数原型如下:

  • 2.4 内核

int request_irq (unsignedintirq,void (*handler)(int,void*,structpt_regs*),unsignedlongfrags,constchar*device,void*dev_id);

  • 2.6 内核

request_irq(unsignedintirq,irq_handler_thandler,unsignedlongflags,constchar*name,void*dev);

参数说明

在发生对应于第 1个参数 irq 的中断时,则调用第 2 个参数handler 为要注册的中断服务函数(也就是把 handler() 中断服务函数注册到内核中 )。

第 3 个参数 flags 指定了快速中断或中断共享等中断处理属性。在 2.6 教新的内核里(我的是 2.6.27 ~ 2.6.31 ),在 linux/interrupt.h 中定义操作这个参数的宏如下:

引用
/*
 * These correspond to the IORESOURCE_IRQ_* defines in
 * linux/ioport.h to select the interrupt line behaviour.  When
 * requesting an interrupt without specifying a IRQF_TRIGGER, the
 * setting should be assumed to be "as already configured", which
 * may be as per machine or firmware initialisation.

#define IRQF_TRIGGER_NONE0x00000000
#define IRQF_TRIGGER_RISING 0x00000001
#define IRQF_TRIGGER_FALLING 0x00000002   
#define IRQF_TRIGGER_HIGH 0x00000004                  
指定中断触发类型:高电平有效。新增加的标志 
#define IRQF_TRIGGER_LOW 0x00000008
#define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
#define IRQF_TRIGGER_PROBE 0x00000010

/*
* These flags used only by the kernel as part of the  irq handling routines.
*                registered first in an shared interrupt is considered for
*                performance reasons)
*/
#define IRQF_DISABLED           0x00000020        * IRQF_DISABLED - keep irqs disabled when calling the action handler
#define IRQF_SAMPLE_RANDOM      0x00000040* IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
#define IRQF_SHARED             0x00000080* IRQF_SHARED - allow sharing the irq among several devices

#define IRQF_PROBE_SHARED       0x00000100* IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
#define IRQF_TIMER              0x00000200* IRQF_TIMER - Flag to mark this interrupt as timer interrupt

#define IRQF_PERCPU             0x00000400* IRQF_PERCPU - Interrupt is per cpu
#define IRQF_NOBALANCING        0x00000800* IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
#define IRQF_IRQPOLL            0x00001000* IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
早期一点的 2.6 内核这里一般以 SA_ 前缀开头,如:

SA_INTERRUPT   表示禁止其他中断;(对应于 IRQF_DISABLED )
SA_SHIRQ             表示共享相同的中断号 (对应于 IRQF_SHARED )
SA_SAMPLE_RANDOM   此宏会影响到 RANDOM 的处理( 对应于 IRQF_SAMPLE_RANDOM )。

第 4 个参数 name,通常是设备驱动程序的名称。改值用在 /proc/interrupt 系统 (虚拟) 文件上,或内核发生中断错误时使用。

第 5 个参数 dev_id 中断名称 可作为共享中断时的中断区别参数,也可以用来指定中断服务函数需要参考的数据地址。建议将设备结构指针作为dev_id参数

int request_irq(unsigned int irq, irq_handler_t handler,
        IRQF_SHARED, const char *devname, void *dev_id)

很多权威资料中都提到,中断共享注册时的注册函数中的dev_id参数是必不可少的,并且dev_id的值必须唯一。那么这里提供唯一的dev_id值的究竟是做什么用的?

根据我们前面中断模型的知识,可以看出发生中断时,内核并不判断究竟是共享中断线上的哪个设备产生了中断,它会循环执行所有该中断线上注册的中断处理函数(即irqaction->handler函数)。因此irqaction->handler函数有责任识别出是否是自己的硬件设备产生了中断,然后再执行该中断处理函数。通常是通过读取该硬件设备提供的中断flag标志位进行判断。那既然kernel循环执行该中断线上注册的所有irqaction->handler函数,把识别究竟是哪个硬件设备产生了中断这件事交给中断处理函数本身去做,那request_irq的dev_id参数究竟是做什么用的?

很多资料中都建议将设备结构指针作为dev_id参数。在中断到来时,迅速地根据硬件寄存器中的信息比照传入的dev_id参数判断是否是本设备的中断,若不是,应迅速返回。这样的说法没有问题,也是我们编程时都遵循的方法。但事实上并不能够说明为什么中断共享必须要设置dev_id。

下面解释一下dev_id参数为什么必须的,而且是必须唯一的。

当调用free_irq注销中断处理函数时(通常卸载驱动时其中断处理函数也会被注销掉),因为dev_id是唯一的,所以可以通过它来判断从共享中断线上的多个中断处理程序中删除指定的一个。如果没有这个参数,那么kernel不可能知道给定的中断线上到底要删除哪一个处理程序。

注销函数定义在Kernel/irq/manage.c中定义: 
    void free_irq(unsigned int irq, void *dev_id)

返回值
函数运行正常时返回 0 ,否则返回对应错误的负值。

示例代码片段

引用

irqreturn_t xxx_interrupt (intirq,void*dev_id)
{
        ...

return (IRQ_HANDLED);
}

int xxx_open (struct inode *inode,structfile*filp)
{
        if (!request_irq (XXX_IRQ,xxx_interruppt,IRQF_DISABLED,"xxx",NULL)){

/*正常注册*/
        }

return (0);
}

request_irq() | 注册中断服务的更多相关文章

  1. request_irq() | 注册中断服务函数【转】

    本文转载自:http://blog.csdn.net/wealoong/article/details/7566546#t0 参考  : ARM Linux 中断机制分析.pdf linux-2.6. ...

  2. RPC原来就是Socket——RPC框架到dubbo的服务动态注册,服务路由,负载均衡演化

    序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用.然我们自己动手从0开始写一个rpc功能以及实 ...

  3. 把解压缩版的tomcat6注册成服务并设置自启动

    操作步骤: 1.在“开始 ”→“运行 ”中输入cmd 命令,进入MS-DOS界面 2.cd 到tomcat的bin目录下       C:/> cd tomcat/bin 3.运行命令servi ...

  4. SpringCloud+Consul 服务注册与服务发现

    SpringCloud+Consul 服务注册与服务发现 1. 服务注册: 在Spring.factories有一段: # Discovery Client Configuration org.spr ...

  5. Windows平台注册mysql服务

    将mysql 注册为服务: ->mysqld --install 卸载服务: ->mysqld --remove 命令行启动mysql: ->net start mysql 命令行关 ...

  6. nginx 注册为服务

    使用java service wrapper将java程序注册为windows服务 分类:Java (5677)  (8) 将java注册为windows服务后,我们就直接可以通过windows的服务 ...

  7. 将OutLook.exe注册为服务,让其一直保持开启状态

    类似于TaobaoProtect.exe是由TBSecSvc服务启动的 http://stackoverflow.com/questions/3582108/create-windows-servic ...

  8. win7中注册tomcat服务

    非安装版tomcat下载后,在bin文件夹会有一个startup.bat文件,运行该文件即可启动tomcat了.不过在服务器配置tomcat的话,就通常需要注册为服务. 在/bin文件下还有tomca ...

  9. 使用javaservice 将jboss 注册为服务

    近来做项目,需要jboss定期重新启动.不想再看到jboss启动那个黑洞洞的窗口,就想着把它注册为服务,然后在net start.恰好objectweb上有个open source的javaservi ...

随机推荐

  1. Extracts

    @1:四层和七层负载均衡的区别:所谓四层负载均衡,也就是主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器.以常见的TCP为例,负载均衡设备在接收到第一个 ...

  2. Kattis - glitchbot 【DFS】

    Kattis - glitchbot [DFS] 题意 有一个机器人 刚开始在(0, 0),然后给出一个目标点,并且会给出一系列指令,但是其中会有一个指令是错误的.我们需要找出那个指令,并且改成正确的 ...

  3. MySQL SQL Injection(注入)

    如果通过网页接收用户输入,而后再把这些数据插入到数据库中,那么你可能就会碰到 SQL 注入式攻击.本节简要介绍如何防范这种攻击,确保脚本和 MySQL 语句的安全性. 注入式攻击往往发生在要求用户输入 ...

  4. 关于Webpage Not Found问题解决~~~

    还是外文网站好,以下解决办法: IIS6.0 UI vs. IIS 7.x UI Series: More about Web Service Extensions This week in the ...

  5. c语言单元测试框架--CuTest

    1.简介 CuTest是一款微小的C语言单元测试框,是我迄今为止见到的最简洁的测试框架之一,只有2个文件,CuTest.c和CuTest.h,全部代码加起来不到一千行.麻雀虽小,五脏俱全,测试的构建. ...

  6. camera corder profile

    /system/etc/ 其中的qulity high 必须与 最大的支持的分辨率相同. 不然cts 不过. 这里的配置必须在报告给app的数据匹配.

  7. 尽可能的构建一个拓展性比"较好"的项目,会让你后期迭代好受点

    转载请注明出处:王亟亟的大牛之路 这礼拜基本都在忙自己项目上的事,然后之后会"重新整理"后把这部分的功能开源出来,这里@下队友 NeglectedByBoss 本周还是没有停更收纳 ...

  8. 如何理解Hibernate的延迟加载机制?在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?

    延迟加载就是并不是在读取的时候就把数据加载进来,而是等到使用时再加载.Hibernate使用了虚拟代理机制实现延迟加载,我们使用Session的load()方法加载数据或者一对多关联映射在使用延迟加载 ...

  9. 多线程-信号量Semaphore

    计数信号量用来控制同时访问某个特定资源的操作数量.Semaphore可以用于实现资源池,例如数据库连接池.我们可以构造一个固定长度的资源池,当资源池为空的时候,请求资源将会阻塞,而不是失败.当资源池非 ...

  10. Android中获取屏幕高度和宽度

    有时我们需要获取当前屏幕的高度和宽度,只需要在一个Activity的onCreate()方法中写上如下代码即可: //定义DisplayMetrics 对象 DisplayMetrics metric ...