我知道这个话题很久以前就被争论过了(链接:interrupt and event 之间的区别),尽管我认为答案不够充分。原因是下一个:当人们谈论事件与中断时,事件一词表示硬件而不是软件。而且,根据那个解释,事件是可以预测的,不是突然发生的事情,但是在唤醒事件的情况下,这不可能是真的,因为这个事件不是“预期的”,它是自发的。例如,可以查看 stm32 数据表并注意到有一个所谓的唤醒事件启用寄存器。这个“事件”既不涉及要执行的特定代码,也不涉及与软件相关的东西。
1 回答
事件是一个更高抽象层的概念,通常出现在系统或应用程序编程中。它们不一定基于硬件,但可以纯粹由软件触发。该术语没有单一的定义,它非常广泛。
另一方面,中断总是由最低级别的硬件触发。另一个术语是硬件异常,上层内核和微控制器通常将它们作为内核抛出的东西或在某些异常情况发生时监督硬件(无效指令、被零除、内存访问错误等)分开。而中断源可能是预期的硬件行为或某些错误条件。
中断和硬件异常需要将处理函数注册到通常称为中断向量表的硬件查找表中。当中断发生时,硬件会到这个表中找到要调用的函数的地址——这些函数被称为中断服务程序(ISR)。将有一个特殊的中断调用约定,其中某些寄存器在调用 ISR 之前由硬件堆叠,并且在 ISR 完成时使用特殊的返回指令来恢复寄存器。
然而,事件使用软件回调函数,通常由应用程序在事件创建时传递函数指针。这就是它们在应用程序编程和快速应用程序开发 (RAD) 工具中的典型使用方式。在嵌入式系统中,可以通过让应用程序为驱动程序内部发生的某些事情注册一些回调来创建类似的东西,然后让驱动程序调用回调。但是即使驱动程序是硬件之上的最低级代码,它仍然是软件并执行由软件设计的调用。
但由于“事件”是一个如此广泛的术语,在某些情况下,事件是可以与更广泛的 API 函数一起使用的对象。然后它们不一定有回调函数——它们本质上只是标志。例如,在 Windows 操作系统中,应用程序程序员可以创建一个事件来向正在运行的线程发出信号,之后线程可以利用 CPU 有效的睡眠功能并等待直到接收到事件。这是通过让它自己优雅地完成来正确停止线程的正常方法之一。
中断和事件的共同点是它们都会导致有效但不确定的执行。当中断/事件没有被触发并且它不需要使用某些标志的轮询时,程序可以做其他事情,这是中断的替代方案。但是当它触发时,它会中止当前的执行并通过执行其他操作来中断它。此外,除了当前调用堆栈之外,它还会在堆栈上推送一些额外的调用,因此如果它发生在程序处于最深调用级别时,您可能会遇到非常微妙的错误,例如间歇性堆栈溢出。
中断和事件的另一个问题是它们通常充当单独的线程,伴随着所有线程安全问题。您需要通过信号量或保证原子访问来保护与 ISR/回调共享的变量免受竞争条件错误的影响。如果不这样做,我会说迄今为止嵌入式系统中最常见的错误。这也会产生非常微妙的错误。