我正在阅读中断。可以通过特殊的中断掩码暂停非关键中断。这称为中断屏蔽。我不知道什么时候/为什么你可能想要或需要暂时挂起中断?可能是信号量,还是在多处理器环境中编程?
4 回答
当操作系统准备运行自己的“让我们编排世界”代码时,它就会这样做。
例如,在某些时候操作系统线程调度程序具有控制权。它在允许线程运行之前准备处理器寄存器和需要完成的所有其他工作,以便为该进程和线程设置环境。然后,在让该线程运行之前,它会设置一个计时器中断,以便在它打算让该线程在 CPU 上拥有的时间过去后引发。
在那个时间段(量子)过去之后,中断被引发并且操作系统调度程序再次控制。它必须弄清楚接下来需要做什么。为此,它需要保存 CPU 寄存器的状态,以便知道如何撤消执行代码的副作用。如果在保存状态时由于任何原因引发另一个中断(例如某些异步 I/O 完成),这将使操作系统处于其世界未处于有效状态的情况下(实际上,保存状态需要原子操作)。
为了避免陷入这种情况,操作系统内核因此在执行任何需要原子的操作时禁用中断。在它完成任何需要做的事情并且系统再次处于已知状态后,它会重新启用中断。
除了已经给出的答案之外,它还有一个优先事项。有些中断是您需要或希望能够尽快响应的,还有一些您想了解的中断,但前提是您不那么忙。最明显的例子可能是重新填充 DVD 刻录机上的写入缓冲区(如果不及时这样做,某些硬件只会错误地写入 DVD)与处理来自网络的新数据包。在收到前者的中断后,您将禁用后者的中断,并在填充缓冲区期间保持禁用状态。
实际上,很多 CPU 都直接在硬件中内置了中断优先级。发生中断时,为较小的中断设置禁用标志,并且通常,该中断与读取中断向量并跳转到相关地址同时发生。指示接收中断也隐含地屏蔽了该中断,直到中断处理程序结束为止,这具有放松对中断硬件的限制的良好副作用。例如,您可以简单地说信号高电平触发中断,并让外部硬件决定它希望将线路保持高电平多长时间,而不必担心无意中触发多个中断。
在许多过时的系统(包括 z80 和 6502)中,往往只有两个级别的中断——可屏蔽和不可屏蔽,我认为这就是启用或禁用中断的语言的来源。但即使早在最初的 68000 中,您也有 8 级中断和 CPU 中的当前优先级,该优先级指示实际允许哪些级别的传入中断生效。
我曾经在一个可能发生大约 10 个中断的 ARM 板上编程。我编写的每个特定程序对其中的四个都不感兴趣。例如,板上有 2 个计时器,但我的程序只使用了 1 个。我会屏蔽第二个计时器的中断。如果我没有屏蔽该计时器,它可能已启用并继续产生中断,这会减慢我的代码速度。
另一个例子是我将使用 UART 接收 REGISTER 完全中断,因此永远不需要发生 UART 接收 BUFFER 完全中断。
我希望这能让您了解为什么要禁用中断。
想象一下,您的 CPU 现在处于“int3”处理程序中,此时“int2”发生并且新发生的“int2”与“int3”相比具有较低的优先级。我们将如何处理这种情况?
一种方法是在处理“int3”时,我们会屏蔽掉其他优先级较低的中断器。也就是说,我们看到“int2”正在向 CPU 发出信号,但 CPU 不会被它中断。在我们处理完“int3”之后,我们从“int3”返回并取消屏蔽较低优先级的中断器。
我们返回的地方可以是:
- 另一个进程(在抢占式系统中)
- 被“int3”中断的进程(在非抢占系统或抢占系统中)
- 一个被 int3 中断的 int 处理程序,比如说 int1 的处理程序。
在情况 1 和 2 中,因为我们取消了较低优先级的中断器,并且“int2”仍在向 CPU 发出信号:“嗨,有件事需要您立即处理”,那么 CPU 在执行指令时会再次被中断从一个进程,处理“int2”
情况3,如果“int2”的优先级高于“int1”,那么CPU在执行“int1”的handler的指令时,会再次中断,去处理“int2”。
否则,“int1”的处理程序将在不中断的情况下执行(因为我们还屏蔽了优先级低于“int1”的中断器),CPU 将在处理完“int1”并取消屏蔽后返回进程。那时将处理“int2”。