【问题标题】:Interrupts disabled during Interrupt handling在中断处理期间禁用中断
【发布时间】:2015-12-25 02:06:38
【问题描述】:

为什么内核当前正在处理中断时会禁用中断?

如果错过了携带重要信息的中断怎么办?

【问题讨论】:

  • 有些内核在中断处理程序中不禁用中断,并且有中断堆栈,允许低优先级的中断被高优先级的中断打断。

标签: operating-system interrupt interrupt-handling


【解决方案1】:

这可以防止可能溢出内核堆栈的“堆栈中断”。它还可以防止死锁和/或“固定”。

大多数硬件不会“丢失”中断。在中断期间,CPU 的“中断标志”被清除,但中断控制器 [一个单独的野兽] 仍然可用/启用以记录新的中断。如果 CPU 正在处理硬件_A 的中断(在“中断服务程序”ISR_A 中),硬件_B 的中断仍然可以被断言。它会被[中断控制器]记住,只是那时它不会中断CPU。当 ISR_A 返回时,中断标志在退出时重新启用,现在,ISR_B 将立即进入(其调用堆栈帧将在与 ISR_A 相同的内存位置开始)。

虽然不会错过/丢弃中断,但 ISR 应该很短 [快速执行] 以尽量减少延迟。换句话说,ISR_A 不应该花费太长时间,以至于 hardware_B 会溢出一些内部状态/缓冲区[因为它在等待 ISR 服务时会继续积累数据]。

最小化延迟是仔细内核设计和 ISR 设计的一部分。在 Linux 中,ISR 可以分解为 ISR 部分和“下半部分”或“tasklet”部分。 ISR [禁用中断] 执行服务/静默设备所需的最低限度(例如,清除设备中的一个位以防止它立即重新声明中断)。

然后它会启用其相应的 tasklet [在启用中断的情况下运行] 来执行可能需要更长时间的更费力的操作。尽管有这个名字,Tasklet 并不像出现在“ps”中的完整的任务/进程。它们是一种 [非常] 轻量级/高效的方式来拆分 ISR 必须完成的工作,以最大限度地减少延迟。

【讨论】:

    【解决方案2】:

    让我们回答每个问题。

    为什么内核当前正在处理中断时会禁用中断?

    虽然有很多种中断类型,例如 I/O、定时器、看门狗、串行端口、外设和 DMA,但让我们以 I/O 为例。我们将讨论一个原始案例并将其扩展到内核中。

    想象一下连接到 CPU 特定中断引脚的火警/传感器位 0/1。 0是正常状态,1是火灾!然后将该输入的中断配置为“电平触发”。传感器触发 1 的那一刻,ISR 必须执行相关代码来警笛或自动拨打消防部门。通常应在您进入 ISR 时清除中断。如果不清除,硬件会不断中断 CPU,ISR 中的安全代码将永远不会执行。

    CPU 还需要维护其当前执行状态的堆栈。反复出现的中断使情况变得复杂。

    “边沿触发”或“转换触发”的第二个示例 假设输入线路/引脚(NRZ 编码)上出现了一系列位。如果 ISR 的工作是将这些位组装成字(8,16,32 任意长度),我们需要清除中断,将位组装到缓冲区中,然后以周期为单位再次启用中断。不清除中断会导致小故障转换将 1 位误认为 2 位。

    所以实践是设置并启用中断,如果中断,清除它,执行 ISR 代码并在相关的地方启用中断。

    内核

    内核本身是一段关键的代码,调度程序(也称为 OS 定时器、OS 时钟)依赖于硬件定时器中断。包含中断逻辑的 CPU 硬件部分维护状态转换。它还具有用于启用、禁用、屏蔽和设置中断优先级的硬连线逻辑。

    如果内核模块或驱动模块应该安全地执行代码,确定性行为只能通过在执行处理程序之前禁用中断来获得。

    如果错过了携带重要信息的中断怎么办?

    中断处理不应太长(在启用中断之前)。应该根据中断的频率和处理程序的复杂性来正确设计代码。

    【讨论】:

      猜你喜欢
      • 2018-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      相关资源
      最近更新 更多