2,856
社区成员




在 Linux 驱动中,中断处理是一个重要的机制,用于处理外部硬件设备产生的异步事件。下面详细介绍中断处理的流程,包含中断的申请、注册以及处理函数的编写。
在进行中断处理之前,需要先确定要处理的中断号。中断号是硬件设备产生中断时的标识,不同的硬件设备有不同的中断号。你可以通过查阅硬件文档、使用系统工具(如 cat /proc/interrupts
)或者参考内核文档来获取中断号。
中断处理函数是在中断发生时被内核调用的函数,其原型如下:
irqreturn_t irq_handler(int irq, void *dev_id);
irq
:表示触发中断的中断号。dev_id
:是一个传递给中断处理函数的设备标识符,可用于区分不同的设备。irqreturn_t
:是中断处理函数的返回值类型,常见的返回值有 IRQ_NONE
(表示中断未被处理)、IRQ_HANDLED
(表示中断已被处理)。以下是一个简单的中断处理函数示例:
#include <linux/interrupt.h>
#include <linux/module.h>
static irqreturn_t my_irq_handler(int irq, void *dev_id) {
printk(KERN_INFO "Interrupt %d occurred!\n", irq);
return IRQ_HANDLED;
}
在驱动模块初始化时,需要使用 request_irq
函数来申请和注册中断处理函数。request_irq
函数的原型如下:
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev_id);
irq
:要申请的中断号。handler
:指向中断处理函数的指针。flags
:中断处理的标志,常见的标志有:IRQF_SHARED
:表示该中断可以被多个设备共享。IRQF_TRIGGER_RISING
:表示上升沿触发中断。IRQF_TRIGGER_FALLING
:表示下降沿触发中断。IRQF_TRIGGER_HIGH
:表示高电平触发中断。IRQF_TRIGGER_LOW
:表示低电平触发中断。name
:中断的名称,用于在 /proc/interrupts
中显示。dev_id
:传递给中断处理函数的设备标识符,如果使用 IRQF_SHARED
标志,则该参数不能为 NULL
。以下是申请和注册中断的示例代码:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#define MY_IRQ_NUMBER 10 // 假设中断号为 10
static irqreturn_t my_irq_handler(int irq, void *dev_id) {
printk(KERN_INFO "Interrupt %d occurred!\n", irq);
return IRQ_HANDLED;
}
static int __init my_driver_init(void) {
int ret;
ret = request_irq(MY_IRQ_NUMBER, my_irq_handler, IRQF_TRIGGER_RISING, "my_irq", NULL);
if (ret) {
printk(KERN_ERR "Failed to request IRQ %d\n", MY_IRQ_NUMBER);
return ret;
}
printk(KERN_INFO "IRQ %d requested successfully\n", MY_IRQ_NUMBER);
return 0;
}
在驱动模块卸载时,需要使用 free_irq
函数来释放之前申请的中断。free_irq
函数的原型如下:
void free_irq(unsigned int irq, void *dev_id);
irq
:要释放的中断号。dev_id
:传递给中断处理函数的设备标识符,与 request_irq
中使用的相同。以下是释放中断的示例代码:
static void __exit my_driver_exit(void) {
free_irq(MY_IRQ_NUMBER, NULL);
printk(KERN_INFO "IRQ %d freed\n", MY_IRQ_NUMBER);
}
module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_LICENSE("GPL");
request_irq
函数申请和注册中断处理函数。free_irq
函数释放中断。通过以上步骤,就可以在 Linux 驱动中实现基本的中断处理功能。需要注意的是,中断处理函数应该尽量简短,避免在其中执行耗时的操作,以免影响系统的响应性能。如果需要进行耗时操作,可以使用工作队列、tasklet 等机制来处理。