FourierFlux Asked: 2024-12-02 01:57:57 +0800 CST2024-12-02 01:57:57 +0800 CST 2024-12-02 01:57:57 +0800 CST 在多处理器系统中,中断会阻止所有执行吗? 772 我读过你不应该在中断处理程序中使用阻塞系统调用。 对于单处理器系统,这是有道理的,但是对于多处理器系统,这样的阻塞操作真的会阻塞整个系统吗?还是只阻塞它所运行的处理器? linux-kernel 1 个回答 Voted Best Answer telcoM 2024-12-02T20:45:54+08:002024-12-02T20:45:54+08:00 依据:https://static.lwn.net/images/pdf/LDD3/ch10.pdf 当处理器接收到中断时,它首先运行一些特定于体系结构的汇编代码,然后跳转到do_IRQ:所有中断所共有的中断处理程序代码的一部分。 摘自段落《x86 上的中断处理内部原理》(上面链接的第 11 页): do_IRQ 所做的第一件事是确认中断,以便中断控制器可以继续执行其他操作。然后,它获取给定 IRQ 号的自旋锁,从而阻止任何其他 CPU 处理此 IRQ。 因此,中断控制器可以生成同一中断的另一个实例,但任何试图处理该中断的处理器都将被自旋锁阻止,直到处理完当前中断实例为止。换句话说,其他处理器/核心不会被阻止执行代码:它们只是被阻止进入当前核心上正在执行的同一中断处理程序。并且阻止是通过自旋锁进行的,因此预期所需的等待时间将非常短。 阻塞系统调用是指等待某事发生的系统调用:在等待时,处理器可以(通常会)被安排运行其他任务。 但是,如果当前核心(正在执行中断处理程序)被安排运行其他任务/进程,它所持有的自旋锁将保持锁定状态。并且无法保证启动中断处理程序的上下文会在合理的时间内再次被安排执行。同时,如果再次发出相同的中断信号,任何试图处理它的处理器都将被保留在自旋锁中。除非等待的中断上下文立即被安排再次执行、完成中断处理并解锁自旋锁,否则所有核心都可能被自旋锁困住,从而完全导致系统死锁。 因此,运行中断处理程序的内核在中断处理程序完成之前不得被安排执行其他任务。更高级别的中断可能会抢占当前中断上下文,但一旦完成,内核必须尽快返回以完成中断处理程序。 因此,“不应该在中断处理程序中使用阻塞系统调用”实际上只是“在执行中断处理程序时,不能将核心调度到其他任务”的一个子集。 (从历史上看,当 Linux 作为单处理器操作系统启动时,曾经有一个且唯一的大内核锁,用于控制对内核许多部分的访问。当添加多处理器支持时,这很快成为一个性能限制问题,并且花费了大量精力从大内核锁过渡到尽可能无锁方法,否则就使用更细粒度的锁定。)
依据:https://static.lwn.net/images/pdf/LDD3/ch10.pdf
当处理器接收到中断时,它首先运行一些特定于体系结构的汇编代码,然后跳转到
do_IRQ
:所有中断所共有的中断处理程序代码的一部分。摘自段落《x86 上的中断处理内部原理》(上面链接的第 11 页):
因此,中断控制器可以生成同一中断的另一个实例,但任何试图处理该中断的处理器都将被自旋锁阻止,直到处理完当前中断实例为止。换句话说,其他处理器/核心不会被阻止执行代码:它们只是被阻止进入当前核心上正在执行的同一中断处理程序。并且阻止是通过自旋锁进行的,因此预期所需的等待时间将非常短。
阻塞系统调用是指等待某事发生的系统调用:在等待时,处理器可以(通常会)被安排运行其他任务。
但是,如果当前核心(正在执行中断处理程序)被安排运行其他任务/进程,它所持有的自旋锁将保持锁定状态。并且无法保证启动中断处理程序的上下文会在合理的时间内再次被安排执行。同时,如果再次发出相同的中断信号,任何试图处理它的处理器都将被保留在自旋锁中。除非等待的中断上下文立即被安排再次执行、完成中断处理并解锁自旋锁,否则所有核心都可能被自旋锁困住,从而完全导致系统死锁。
因此,运行中断处理程序的内核在中断处理程序完成之前不得被安排执行其他任务。更高级别的中断可能会抢占当前中断上下文,但一旦完成,内核必须尽快返回以完成中断处理程序。
因此,“不应该在中断处理程序中使用阻塞系统调用”实际上只是“在执行中断处理程序时,不能将核心调度到其他任务”的一个子集。
(从历史上看,当 Linux 作为单处理器操作系统启动时,曾经有一个且唯一的大内核锁,用于控制对内核许多部分的访问。当添加多处理器支持时,这很快成为一个性能限制问题,并且花费了大量精力从大内核锁过渡到尽可能无锁方法,否则就使用更细粒度的锁定。)