c - 设备驱动程序和轮询中的中断处理

标签 c linux-device-driver interrupt-handling

我将仔细研究一些大致执行以下操作的代码:

  • 内核驱动程序处理中断。
  • 有 1 条中断线,因此当中断发生时,句柄会读取 32 位寄存器,该寄存器会告诉您中断的原因。
  • 对于设置的每个位,它都会调用 ack_irq() 来清除中断,并将中断原因写入驱动程序中的缓冲区以供进一步 read()。
  • 接下来,它调用wake_up_interruptible()来唤醒在select()上休眠的用户空间进程。
  • 相应的 poll() 函数执行 poll_wait() 操作。
  • 一旦 select 返回,用户空间就会从驱动程序中 read() 。

虽然我只了解 1 位的基本操作,但以下情况会发生什么:

  • 发生中断,并设置 1 位。
  • 处理程序调用wake_up_interruptible()。 poll() 返回。
  • 用户空间唤醒,开始read()。
  • 现在,另一个中断发生 -> 内核处理该中断并调用wake_up_interruptible(),但现在没有人不等待该事件。

这是否意味着会错过第二个中断?如果是这样,有什么方法可以克服这个问题?

最佳答案

中断处理程序的任务是尽快处理中断。

为了与系统的其余部分进行通信,ISR 使用(循环)缓冲区来放置您的原因。它在中断禁用状态下执行此操作。

一旦中断被处理,系统就会继续。如果用户进程现在想要检查循环缓冲区中是否有新事件,则它需要对该缓冲区进行独占访问。为此,它必须禁用中断(优先级高于 ISR)。它禁用中断,获取缓冲区的下一个元素,更新缓冲区指针或索引并重新启用中断。

如果有新的中断进来,那么直到用户进程重新启用中断(IRQ 线保持高电平,芯片寄存器尚未被读取)之前,它不会被处理。不用说,此缓冲区访问也必须尽可能快(指令尽可能少)。重新启用中断后,新的待处理中断将得到服务。

从缓冲区中获取下一项后,它将其交给功能用户进程。如果缓冲区中没有项目,它就会休眠。当一个项目到达时,它将被唤醒,禁用中断,获取该项目,重新启用中断并返回到用户进程。

这样就不会错过任何中断。

关于c - 设备驱动程序和轮询中的中断处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47950688/

相关文章:

arm - 什么是传统中断?

c - 我对 n*log(N) Big O 的样子很感兴趣

c - 当编译到 gnu99 时,获取 "implicit declaration of function ' fcloseall' 在 C99 中无效”

c - 如何查找由于信号 SIGSEGV、Segmentation failure 导致的错误?

c - 在c中实现通用堆栈

linux - 通过用户空间 I/O (UIO) Linux 驱动程序与 QEMU edu 设备连接

linux - 如何判断一个函数是否可以休眠?

linux - 我自己的 linux Chorded 键盘驱动程序和我的嵌入式应用程序的接口(interface)

networking - ixgbe : setting the number of RX/TX queues

功能与中断调用中的上下文切换?