linux内核中存在专门的中断函数,也就是中断处理程序,用于响应硬件触发的中断信号,是内核与硬件交互的核心机制之一。内核为中断处理提供了一套完整的框架,开发者可以通过标准接口注册自定义的中断处理逻辑,适配不同的硬件设备。

linux内核中断的基本概念
中断是硬件向处理器发送的信号,用于通知处理器有事件发生需要立即处理。linux内核会为每个中断号分配对应的中断处理程序,当硬件触发中断时,处理器会暂停当前执行的任务,跳转到对应的中断处理程序执行,处理完成后再恢复之前的任务。
内核中的中断处理程序分为两个部分,分别是上半部(top half)和下半部(bottom half)。上半部处理非常紧急、不能延迟的任务,比如读取硬件状态、清除中断标志,执行时间要尽可能短。下半部用于处理耗时较长的任务,比如数据拷贝、协议解析,避免阻塞其他中断的响应。
如何注册中断处理函数
linux内核提供了request_irq函数,供驱动开发者注册中断处理程序,该函数的原型如下:
#include <linux/interrupt.h>
/**
* 注册中断处理函数
* @irq: 中断号,对应硬件的中断线
* @handler: 中断处理函数的指针
* @flags: 中断触发标志,比如IRQF_SHARED表示多个设备共享该中断
* @name: 中断的名称,会出现在/proc/interrupts中
* @dev: 传递给中断处理函数的私有数据,共享中断时用于区分不同设备
* @return: 0表示注册成功,负数表示失败
*/
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev);
对应的中断处理函数需要符合irq_handler_t的类型定义,格式如下:
/**
* 中断处理函数
* @irq: 触发的中断号
* @dev: 注册时传入的私有数据
* @return: 返回IRQ_HANDLED表示中断处理完成
*/
irqreturn_t demo_irq_handler(int irq, void *dev)
{
// 上半部处理逻辑,读取硬件状态、清除中断标志等
// ...
return IRQ_HANDLED;
}
当驱动不再需要使用中断时,需要调用free_irq函数释放中断资源,避免资源泄漏:
/** * 释放中断 * @irq: 要释放的中断号 * @dev: 注册时传入的私有数据,需要和request_irq时的参数一致 */ void free_irq(unsigned int irq, void *dev);
中断处理的相关注意事项
- 中断处理函数中不能调用可能会睡眠的函数,比如
kmalloc带GFP_KERNEL标志、copy_from_user等,因为中断上下文是不允许睡眠的。 - 中断处理程序执行时,当前CPU的中断是被禁用的,所以要尽可能缩短上半部的执行时间,避免影响其他中断的响应。
- 如果需要处理耗时任务,应该使用下半部机制,比如软中断、tasklet或者工作队列,将耗时操作放到下半部执行。
- 共享中断的情况下,多个设备共用同一个中断号,中断处理函数中需要通过
dev参数区分不同的设备,并且只有确认是当前设备触发的中断才返回IRQ_HANDLED。
中断相关的常用查看方式
可以通过/proc/interrupts文件查看系统中所有中断的统计信息,包括每个中断号的触发次数、对应的中断名称、处理的CPU核心等:
cat /proc/interrupts
该文件的内容示例如下:
CPU0 CPU1
0: 45 0 IO-APIC 2-edge timer
1: 23 12 IO-APIC 1-edge i8042
8: 1 0 IO-APIC 8-edge rtc0
9: 0 0 IO-APIC 9-fasteoi acpi
12: 120 89 IO-APIC 12-edge i8042
16: 12345 6789 IO-APIC 16-fasteoi ehci_hcd:usb1, snd_hda_intel
其中16号中断是共享中断,同时被usb控制器和声卡驱动使用,这也是共享中断的典型场景。
linux_kernelinterrupt_handlerirq_requesttop_halfbottom_half修改时间:2026-06-14 04:30:17