服务器测评网
我们一直在努力

Linux中断注册流程是怎样的?设备树如何配置中断?

Linux 中断注册的核心机制

在 Linux 内核中,中断是硬件与操作系统交互的重要方式,它允许硬件在需要时暂停当前进程的处理,转而请求内核响应,中断注册则是内核管理硬件中断的关键步骤,涉及中断号的申请、中断处理函数的绑定以及中断资源的释放等操作,正确理解中断注册的流程和注意事项,对于驱动开发者和内核开发者至关重要。

Linux中断注册流程是怎样的?设备树如何配置中断?

中断的基本概念

中断分为硬件中断和软件中断,硬件中断由外部设备(如键盘、网卡)触发,通过中断控制器(如 APIC)传递给 CPU;软件中断则由程序通过指令(如 int 0x80)触发,本文主要讨论硬件中断的注册流程。

Linux 内核通过中断描述符表(IDT)管理中断,每个中断号对应一个处理函数,当硬件触发中断时,CPU 会根据中断号查找 IDT,并执行相应的处理函数,驱动开发者需要通过内核提供的 API,将自定义的中断处理函数注册到指定的中断号上。

中断注册的主要 API

Linux 内核提供了多种中断注册的 API,以适应不同的场景需求,最常用的函数是 request_irq(),其原型如下:

int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,  
                const char *name, void *dev);  
  • irq:要注册的中断号,通常通过设备树或平台资源获取。
  • handler:中断处理函数,类型为 irq_handler_t,其原型为 irqreturn_t (*handler)(int, void *)
  • flags:中断标志位,如 IRQF_SHARED(共享中断)、IRQF_TRIGGER_RISING(上升沿触发)等。
  • name:中断名称,用于 /proc/interrupts 等文件显示,便于调试。
  • dev:设备标识符,用于共享中断时的区分,通常为设备结构体指针。

内核还提供了 devm_request_irq() 函数,它通过设备管理资源,可以在设备移除时自动释放中断,避免内存泄漏。

中断处理函数的设计

中断处理函数是中断注册的核心,其设计需遵循以下原则:

Linux中断注册流程是怎样的?设备树如何配置中断?

  1. 执行效率高:中断处理函数应尽量简短,避免耗时操作(如休眠、内存分配),复杂操作应通过 taskletworkqueue 等机制延迟执行。
  2. 可重入性:中断可能被嵌套或重复触发,处理函数需确保在并发执行时的安全性。
  3. 返回值规范:返回 IRQ_NONE 表示中断未处理,返回 IRQ_HANDLED 表示已处理。

一个简单的中断处理函数如下:

static irqreturn_t my_interrupt_handler(int irq, void *dev_id) {  
    // 读取硬件状态,确认中断来源  
    if (/* 中断条件满足 */) {  
        // 处理中断事件  
        return IRQ_HANDLED;  
    }  
    return IRQ_NONE;  
}  

中断标志位的配置

flags 参数决定了中断的行为,常见的标志位包括:

  • IRQF_TRIGGER_NONE:电平触发(默认)。
  • IRQF_TRIGGER_RISING/IRQF_TRIGGER_FALLING:边沿触发。
  • IRQF_SHARED:允许多个设备共享同一中断线,需配合 dev 参数使用。

标志位的配置必须与硬件规格一致,否则可能导致中断无法正常触发或系统不稳定,PCI 设备通常使用边沿触发,而 ISA 设备多用电平触发。

中断的共享机制

多个设备可以共享同一中断线,此时需设置 IRQF_SHARED 标志,并为每个设备提供唯一的 dev 标识符,内核会按顺序调用所有注册的中断处理函数,直到某个函数返回 IRQ_HANDLED,共享中断的典型场景包括 PCI 设备,多个设备可能连接到同一个中断引脚。

中断的释放

当设备不再需要中断时,需调用 free_irq() 释放资源:

Linux中断注册流程是怎样的?设备树如何配置中断?

void free_irq(unsigned int irq, void *dev);  

对于 devm_request_irq() 注册的中断,内核会在设备卸载时自动释放,无需手动调用。

中断注册的注意事项

  1. 中断号的合法性:在注册前需确认中断号未被其他设备占用,可通过 /proc/interrupts 查看当前中断分配情况。
  2. 上下文环境:中断处理函数运行在中断上下文,不能调用休眠或调度相关的函数(如 kmalloc(GFP_KERNEL))。
  3. 错误处理request_irq() 可能返回错误码(如 -EBUSY),需检查返回值并处理异常情况。

实际应用示例

以下是一个简化的中断注册流程:

  1. 获取中断号:通过 platform_get_irq() 从平台设备中获取中断号。
  2. 注册中断:调用 request_irq() 注册处理函数。
  3. 中断处理:在中断处理函数中读取硬件状态并触发后续操作。
  4. 释放资源:在设备移除时调用 free_irq()
int my_driver_probe(struct platform_device *pdev) {  
    int irq = platform_get_irq(pdev, 0);  
    if (irq < 0) {  
        return irq;  
    }  
    return request_irq(irq, my_interrupt_handler, IRQF_SHARED,  
                       "my_device", pdev);  
}  
int my_driver_remove(struct platform_device *pdev) {  
    int irq = platform_get_irq(pdev, 0);  
    free_irq(irq, pdev);  
    return 0;  
}  

Linux 中断注册是驱动开发的基础环节,涉及中断号的申请、处理函数的绑定、标志位的配置以及资源的释放,开发者需严格遵循内核规范,确保中断处理的高效性和安全性,通过合理使用 request_irq()devm_request_irq() 等接口,结合硬件特性配置中断标志,可以实现稳定可靠的中断管理,在实际开发中,还需结合调试工具(如 /proc/interrupts/proc/irq)排查中断相关问题,提升系统的健壮性。

赞(0)
未经允许不得转载:好主机测评网 » Linux中断注册流程是怎样的?设备树如何配置中断?