Linux中断服务大多数情况下,一个驱动程序只需要为它的设备注册一个中断处理例程,当有中断时进行正确的处理。内核负责维护了一个中断服务信号线的注册表,驱动程序在启动中断服务前会请求一个中断通道,使用完后会释放。
注册中断服务函数:
中断注册是使用了的”requset_irq“函数:
1 2 3 4 5 6 7 8 9 | extern int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev); irq:申请的硬件中断号 handler:向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它 *name:中断名称,在/proc/interrupts中可以看到此名称 *dev:在中断共享时会用到,让handler知道是处理哪个中断,也可以用来指定中断服务函数需要参考的数据地址,一般设置为这个设备的设备结构体或者NULL flags:中断处理的属性,详细参数在中说明.详细看代码1 |
代码1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /* * These flags used only by the kernel as part of the * irq handling routines. * * IRQF_DISABLED - keep irqs disabled when calling the action handler. * DEPRECATED. This flag is a NOOP and scheduled to be removed * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator * IRQF_SHARED - allow sharing the irq among several devices * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur * IRQF_TIMER - Flag to mark this interrupt as timer interrupt * IRQF_PERCPU - Interrupt is per cpu * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is * registered first in an shared interrupt is considered for * performance reasons) * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished. * Used by threaded interrupts which need to keep the * irq line disabled until the threaded handler has been run. * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set * IRQF_NO_THREAD - Interrupt cannot be threaded */ #define IRQF_DISABLED 0x00000020 #define IRQF_SAMPLE_RANDOM 0x00000040 #define IRQF_SHARED 0x00000080 #define IRQF_PROBE_SHARED 0x00000100 #define __IRQF_TIMER 0x00000200 #define IRQF_PERCPU 0x00000400 #define IRQF_NOBALANCING 0x00000800 #define IRQF_IRQPOLL 0x00001000 #define IRQF_ONESHOT 0x00002000 #define IRQF_NO_SUSPEND 0x00004000 #define IRQF_FORCE_RESUME 0x00008000 #define IRQF_NO_THREAD 0x00010000 #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD) |
关闭中断服务函数:
1 2 | extern void disable_irq(unsigned int irq); irq:需要屏蔽的硬件中断号 |
使能中断服务函数:
1 2 | extern void enable_irq(unsigned int irq); irq:需要使能硬件中断号 |
释放中断服务函数:
1 2 3 | void free_irq (unsigned int irq, void *dev_id); irq:将要注销掉的中断服务函数的中断号; dev_id:值指定与"request_irq()"函数中使用的"dev_id"值相同的值 |
中断处理例程的返回值说明:
中断处理例程应当返回一个值指示是否真正处理了一个中断。如果处理例程发现设备确实需要处理,应当返回”IRQ_HANDLED”; 否则返回值”IRQ_NONE”。
下面是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #ifndef _LINUX_IRQRETURN_H #define _LINUX_IRQRETURN_H /** * enum irqreturn * @IRQ_NONE interrupt was not from this device * @IRQ_HANDLED interrupt was handled by this device * @IRQ_WAKE_THREAD handler requests to wake the handler thread */ enum irqreturn { IRQ_NONE = (0 << 0), IRQ_HANDLED = (1 << 0), IRQ_WAKE_THREAD = (1 << 1), }; typedef enum irqreturn irqreturn_t; #define IRQ_RETVAL(x) ((x) != IRQ_NONE) #endif |
当硬件中断到达处理器时, 内核提供的一个内部计数器会递增,产生的中断报告显示在”/proc/interrupts”中。这一方法可以用来检查设备是否按预期地工作。此文件只显示当前已安装处理例程的中断的计数。若以前request_irq的一个中断,现在已经free_irq了,那么就不会显示在这个文件中,但是它可以显示终端共享的情况。
“/proc/stat”记录了几个关于系统活动的底层统计信息, 包括(但不仅限于)自系统启动以来收到的中断数。 stat 的每一行以一个字符串开始, 是该行的关键词:intr 标志是中断计数。第一个数是所有中断的总数, 而其他每一个代表一个单独的中断线的计数, 从中断 0 开始(包括当前没有安装处理例程的中断),无法显示终端共享的情况。
以上两个文件的一个不同是:”/proc/interrupts”几乎不依赖体系,而”/proc/stat”的字段数依赖内核下的硬件中断,其定义在
粤ICP备09088251号