it-swarm.cn

在Linux中如何处理中断?

我只知道Interrupthardware signal assertion在处理器引脚中引起。但是我想知道Linux OS是如何处理它的。
发生中断时会发生什么事情?

35
Sen

这是低级处理的高级视图。我正在描述一个简单的典型体系结构,实际体系结构可以更复杂,也可以不同,而在这种详细程度上无关紧要。

interrupt 发生时,处理器将检查是否屏蔽了中断。如果是这样,则直到将它们揭开为止,什么都不会发生。当中断被屏蔽时,如果有任何待处理的中断,则处理器会选择一个。

然后,处理器通过跳转到内存中的特定地址来执行中断。该地址处的代码称为 中断处理程序 。当处理器分支到那里时,它将屏蔽中断(因此中断处理程序具有排他控制权)并将某些寄存器的内容保存在某个位置(通常是其他寄存器)。

中断处理程序通常通过与触发中断的外设进行通信来发送或接收数据,从而完成其必须执行的操作。如果中断是由计时器引起的,则处理程序可能会触发OS调度程序以切换到其他线程。处理程序完成执行后,将执行一条特殊的中断返回指令,该指令可恢复保存的寄存器并取消屏蔽中断。

中断处理程序必须快速运行,因为它阻止了其他中断的运行。在Linux内核中,中断处理分为两部分:

  • “上半部分”是中断处理程序。它执行最少的操作,通常与硬件通信并在内核内存中的某个位置设置标志。
  • “下半部分”执行任何其他必要的处理,例如将数据复制到进程内存,更新内核数据结构等。由于它在启用了中断的情况下运行,因此可能要花费一些时间甚至阻塞系统的其他部分。

与本主题一样,有关更多信息,请阅读 Linux Device Drivers ;。 第10章 关于中断。

40

Gilles已经 已描述 中断的一般情况,以下内容专门适用于Intel架构上的Linux 2.6(部分内容也基于Intel的规范)。

中断是改变处理器执行指令顺序的事件。
有两种不同的中断:

  • CPU在处理指令时产生的同步中断(Exception)
  • 其他硬件设备发出的异步中断(Interrupt)

异常是由内核必须处理的编程错误(例如Divide错误Page FaultOverflow)引起的。他向程序发送信号,并尝试从错误中恢复。

归类为以下两个例外:

  • CPU在检测到异常情况时生成的处理器检测到的异常;分为三组:错误一般可以纠正,陷阱报告执行,中止是严重的错误。
  • 程序员请求的程序化异常,像陷阱一样处理。

中断可由I/O设备(键盘,网络适配器,..),间隔计时器和(在多处理器系统上)其他CPU发出。发生中断时,CPU必须停止其当前指令并执行新到达的中断。他需要保存旧的中断过程状态以(可能)在处理中断后恢复它。

处理中断是一项敏感的任务:

  • 中断随时可能发生,内核会尽力将其移开
  • 一个中断可以被另一个中断打断
  • 内核中的某些区域根本不能被中断

定义了两种不同的中断级别:

  • I/O设备发出的可屏蔽中断;可以处于两种状态,已屏蔽或未屏蔽。仅处理未屏蔽的中断。
  • 不可屏蔽的中断;严重故障(例如硬件故障);始终由CPU处理。

每个硬件设备都有自己的中断请求(IRQ)线。 IRQ从0开始编号。所有IRQ线都连接到可编程中断控制器(PIC)。 PIC侦听IRQ,并将其分配给CPU。也可以禁用特定的IRQ线。
现代多处理Linux系统通常包括较新的高级PIC(APIC),该API在CPU之间平均分配IRQ请求。

中断或异常与处理之间的中间步骤是中断描述符表(IDT)。该表将每个中断或异常向量(一个数字)与一个指定的处理程序关联(例如Divide error由函数divide_error()处理)。

通过IDT,内核确切知道如何处理发生的中断或异常。


那么,中断发生时内核将如何处理?

  • CPU在每条指令之后检查(A)PIC是否存在IRQ
  • 如果是这样,请咨询IDT以将接收到的向量映射到函数
  • 检查中断是否由授权来源发出
  • 保存中断进程的寄存器
  • 调用相应的函数来处理中断
  • 加载最近保存的中断进程的寄存器,然后尝试恢复它
22
wag

首先,涉及中断处理的参与者是外围硬件设备,中断控制器,CPU,操作系统内核和驱动程序。外围硬件设备负责产生中断。当他们希望引起操作系统内核的注意时,他们声明中断请求行。这些信号由中断控制器多路复用,后者负责中断信号的收集。它还负责确定将中断信号传递到CPU的顺序。中断控制器能够暂时禁用特定的中断请求线(IRQL),然后再次将其重新启用(IRQL屏蔽)。中断控制器将收集到的中断请求顺序传递给CPU。完成每条指令的执行后,CPU会检查中断控制器是否有任何等待中的中断请求。如果CPU发现有等待请求并且在内部CPU控制寄存器中设置了中断允许标志,则CPU开始中断处理。如您所见,通过对CPU中的Interrupt标志进行操作并与中断控制器进行通信,Linux内核能够控制中断的接受。例如,Linux可以禁用来自特定设备的中断接受或完全禁用中断接受。

处理器收到中断请求后会怎样?首先,CPU通过复位中断标志自动禁用中断。中断处理完成后,将重新启用它们。同时,CPU进行了将CPU从用户模式切换到内核模式所需的最少工作量,从而使它可以恢复中断代码的执行。 CPU咨询Linux内核填充的特殊CPU控制结构,以找到将控制传递给的代码地址。该地址是中断处理程序的第一条指令的地址,它是Linux内核的一部分。

作为中断处理的第一步,内核将识别接收到的中断向量,以识别系统中发生了哪种事件。中断向量定义了Linux将采取哪些措施来处理它。第二步,Linux将保存其余的CPU寄存器(不会自动由CPU保存),并且可能被中断的程序使用。这是非常重要的动作,因为它允许Linux对中断的程序透明地处理中断。第三步,Linux通过设置内核环境并设置所需的CPU状态来完成切换到内核模式。最后,依赖于向量的中断处理程序被调用。 (您可以在Arch\x86\kernel\entry_32.S中查看BUILD_INTERRUPT3宏,以获取x86体系结构相关示例的其他详细信息)对于外围设备,这是一个do_IRQ()例程。 (查看Arch\x86\kernel\irq.c)

向量相关的中断处理程序通常由对irq_enter()和irq_exit()的调用包装。一对这些函数中包含的代码区域,相对于任何其他此类区域而言是原子的,并且对于cli/sti对而言也是原子的。 Irq_enter()和irq_exit()也捕获一些与中断处理有关的统计信息。最后,内核查看vector_irq表,以找到分配给接收到的中断向量的irq编号,并调用handle_irq()(来自Arch\x86\kernel\irq_32.c)。

至此,Linux中中断处理的公共部分结束了,因为内核将设备驱动程序安装的与设备相关的中断处理程序作为irq描述符的一部分,并将其调用。如果驱动程序未安装此类处理程序,则内核只需在中断控制器上确认中断,然后退出常规中断处理程序即可。

中断处理结束后,内核将恢复先前被中断的程序的状态,并恢复该程序的执行。

8
ZarathustrA

从理论上讲,几乎所有内容都已得到解释。但是,如果您正在寻找有关内核中断处理代码框架的说明,则应使用以下链接: 代码进入内核中断处理内部

而且,如果您仍在研究有关中断和中断处理程序的理论,那么我建议阅读以下内容: 了解中断和中断处理程序

3
trukna