我正在阅读 Linux 内核开发并在 tasklets 章节(https://doc.lagout.org/operating%20system%20/linux/Linux%20Kernel%20Development%2C%203rd%20Edition.pdf page143)中感到困惑。在 tasklet_schedule 函数中,中断状态被保存,而在 taslet_action 中则没有。作者解释说,上下文没有保存在 taslet_action 中,因为该函数知道始终启用中断。我不明白这组中断如何影响保存上下文?谢谢!
2 回答
作者指出 tasklet_schedule 可以在禁用或启用中断的情况下调用。由于它希望它们被禁用,它需要保存它们是否已经被禁用。然后在工作完成后,它知道是否启用它们(如果它们在调用之前启用,则启用它们,如果它们在调用之前禁用,则使它们禁用)。相反,tasklet_action 仅在启用中断的情况下调用,因此检查它们的状态没有意义。他们总是在返回时被禁用和启用。
在 tasklet_schedule 的情况下:
当我们在调度一个小任务时,我们不希望中断打扰我们,所以我们必须禁用它。但是我们也知道,当我们完成调度 tasklet 后,我们希望回到调用调度 tasklet 之前的 IRQ 状态。为此,我们在做任何事情之前保存 IRQ 寄存器的状态,然后根据我们的要求禁用 IRQ,进行调度,现在在返回之前恢复 IRQ 的状态,然后从函数返回。
现在来到复杂的部分,为什么我们在执行 tasklet 时不需要保存 IRQ,即当处理程序调用 tasklet 函数时?要了解我们需要看两个不同的段落:
在第 141 页:
软中断处理程序在启用中断的情况下运行并且不能休眠。当处理程序运行时,当前处理器上的软中断被禁用。但是,另一个处理器可以执行其他软中断。如果在执行时再次引发相同的软中断,则另一个处理器可以同时运行它。
因此,这声明始终启用中断。
现在转到第 143 页:
- 禁用本地中断传递(不需要先保存它们的状态,因为这里的代码总是作为 softirq 处理程序调用并且总是启用中断)并检索此处理器的 tasklet_vec 或 tasklet_hi_vec 列表
所以我们可以得出结论,我们不需要保存 IRQ 状态,因为我们已经知道它的状态,并且在所有情况下都会保持这种状态,所以我们只需禁用 IRQ 并稍后启用它。