Linux kernel 设备驱动程序中的中断处理

Linux kernel 设备驱动程序中的中断处理,linux-kernel,kernel,linux-device-driver,interrupt,interrupt-handling,Linux Kernel,Kernel,Linux Device Driver,Interrupt,Interrupt Handling,我已经编写了一个简单的字符驱动程序,在gpio引脚上请求IRQ,并为此编写了一个处理程序 err=请求irq(irq、irq处理器、IRQF共享、IRQF触发器上升、中断设备名称、raspi gpio devp) 静态irqreturn\u t irq\u处理程序(int-irq,void*arg) 现在从理论上我知道,在中断时,中断控制器会告诉处理器调用do_IRQ(),这将检查IDT并调用我的中断处理程序 内核如何知道中断处理程序是针对这个特定的设备文件的 我还知道中断处理程序不会在任何进程

我已经编写了一个简单的字符驱动程序,在gpio引脚上请求IRQ,并为此编写了一个处理程序

err=请求irq(irq、irq处理器、IRQF共享、IRQF触发器上升、中断设备名称、raspi gpio devp)

静态irqreturn\u t irq\u处理程序(int-irq,void*arg)

现在从理论上我知道,在中断时,中断控制器会告诉处理器调用do_IRQ(),这将检查IDT并调用我的中断处理程序

内核如何知道中断处理程序是针对这个特定的设备文件的

我还知道中断处理程序不会在任何进程上下文中运行。但假设我正在访问在处理程序范围外声明的任何变量,一个静态全局标志=0,在处理程序中,我使标志=1,指示发生了中断。该变量位于流程上下文中。所以我很困惑这个处理程序如何不在任何流程上下文中修改流程上下文中的变量


谢谢

内核不知道中断属于哪个设备。单个中断可以在多个设备之间共享。以前这是很普遍的。由于在中断控制器中改进了中断支持,并引入了消息信号中断,因此这种情况变得越来越少。驱动程序必须确定中断是否来自设备(即设备是否需要“服务”)

您可以通过提供的“void*arg”为中断处理程序提供上下文。这永远不应该是特定于进程的上下文,因为进程可能会退出,留下悬空的指针(即引用已释放和/或可能为其他目的重新分配的内存)

全局变量不是“在流程上下文中”。它是在每一个上下文中——或者如果你愿意的话,没有上下文。当您听到“不在进程上下文中”时,这意味着几件事:(1)您不能阻止/睡眠(因为您将使哪个进程处于睡眠状态?)(2)您不能对用户空间虚拟地址进行任何引用(因为这些引用指向什么?)(3)您不能对“当前任务”进行引用(因为没有或不知道)

通常,驱动程序的中断处理程序将数据推送或拉入“驱动程序全局”数据区,驱动程序的进程上下文端可以从该数据区/向该数据区传输数据。

内核不知道该特定中断是针对特定设备的

它唯一知道的是它必须调用
irq\u处理程序
,并将
raspi\u gpio\u devp
作为参数(如下所示:
irq\u处理程序(irq,raspi\u gpio\u devp)

如果您的irq线路是共享的,您应该检查您的设备是否生成了irq。代码:

int irq_handler(int irq, void* dev_id) {
    struct raspi_gpio_dev *raspi_gpio_devp = (struct raspi_gpio_dev *) dev_id;
    if (!my_gpio_irq_occured(raspi_gpio_devp))
        return IRQ_NONE;
    /* do stuff here */
    return IRQ_HANDLED;
}
中断处理程序在中断上下文中运行。但是您可以访问在中断范围之外声明的静态变量

通常,中断处理程序所做的是:

  • 检查中断状态
  • 从硬件中检索信息并将其存储在某处(例如缓冲区/fifo)
  • wake\u up()
    等待该信息的内核进程
如果您想对中断处理的“做”和“不做”真正有信心,那么最好了解一下内核的进程是什么


一本关于这方面的好书是

这是回答你的问题:-

内核如何知道中断处理程序是针对这个特定的>设备文件的

  • 每个片上系统文档都会提到连接到不同中断线的不同设备的中断编号

  • 对于设备驱动程序的实例化,必须在设备树条目中提及相同的中断号

  • 设备驱动程序的常用探测函数解析设备树数据结构,读取IRQ编号,并使用register\u IRQ函数注册处理程序

  • 如果一个IRQ编号/行中有多个设备,那么IRQ状态寄存器(如果映射到同一VM空间下,则针对不同的设备)可以在IRQ处理程序中使用以区分


  • 请阅读my

    中的更多内容,我如何编写代码来确定中断是针对我的设备的…将irq参数与已知的irq值进行比较?因此,我谈论的这个全局变量,例如:指示中断已发生的int标志,应该位于每设备结构的a侧,该结构应作为void*arg???Typicall传递给处理程序你可以询问你的设备。如果你的设备不能告诉你它是否产生了中断,那么你需要确保中断线没有被共享(去掉IRQF_shared)。无论你想用它做什么,“void*arg”都是可用的。通常,它指向某种特定于设备的数据结构(因为一个设备可能有多个实例)。您也可以将全局数据保存在全局/静态变量中。