事件和中断之间的区别

问题描述

我知道这个话题很久以前就被讨论过(链接Difference between interrupt and event),尽管如此,我认为答案不够充分。原因是下一个:当人们谈论事件与中断时,术语事件表示硬件而不是软件。此外,根据那个解释,一个事件是可以预测的,不是突然发生的事情,但是,在唤醒事件的情况下,这不可能是真的,因为这个事件不是“预期的”,它是自发的。例如,您可能会查看 stm32 数据表并注意到有一个所谓的唤醒事件使能寄存器。这个“事件”既不涉及要执行的特定代码段,也不涉及与软件相关的内容

解决方法

事件是一个更高的抽象层概念,通常出现在系统或应用程序编程中。它们不一定基于硬件,但可以纯粹由软件触发。这个术语没有单一的定义,它非常广泛。

另一方面,中断总是由最低级别的硬件触发。另一个术语是硬件异常,上层内核和微控制器通常将那些异常情况(无效指令、除以零、内存访问错误等)作为内核或监督硬件抛出的东西分开。而中断源可能是预期的硬件行为或某些错误条件。

中断和硬件异常需要在硬件查找表中注册处理函数,通常称为中断向量表。当中断发生时,硬件将转到该表以查找要调用的函数的地址——此类函数被命名为中断服务例程 (ISR)。中断会有一个特殊的调用约定,其中某些寄存器在调用 ISR 之前由硬件堆叠,并且在 ISR 完成时使用特殊的返回指令来恢复寄存器。

然而,事件使用软件回调函数,通常由应用程序在创建事件时传递函数指针。这就是它们在应用程序编程和快速应用程序开发 (RAD) 工具中的典型使用方式。在嵌入式系统中,可以通过让应用程序为驱动程序内部发生的某些事情注册多个回调,然后让驱动程序调用回调来创建类似的东西。但即使驱动程序是硬件之上的最底层代码,它仍然是软件并执行由软件设计的调用。

但由于“事件”是一个如此宽泛的术语,在某些情况下,事件是可以与更广泛的 API 函数一起使用的对象。然后它们不一定有回调函数——它们本质上只是标志。例如,在 Windows 操作系统中,应用程序程序员可以创建一个事件来向正在运行的线程发送信号,然后线程可以利用 CPU 有效的睡眠功能并等待直到接收到事件。这是通过让它自己优雅地结束来正确停止线程的正常方法之一。

中断和事件的共同点是它们都导致有效但不确定的执行。当中断/事件没有触发并且不需要使用轮询某些标志时,程序可以做其他事情,这是中断的替代方法。但是当它触发时,它会中止当前的执行并通过执行其他操作来中断它。此外,除了当前的调用堆栈之外,它还会在堆栈上推送一些额外的调用,因此如果在程序处于最深调用级别时发生这种情况,您可能会遇到非常微妙的错误,例如间歇性堆栈溢出。

中断和事件的另一个问题是,它们通常作为单独的线程运行,所有线程安全问题都随之而来。您需要通过信号量或通过保证原子访问来保护与 ISR/回调共享的变量免受竞争条件错误的影响。如果不这样做,我认为这是迄今为止嵌入式系统中最常见的错误。这也会产生令人难以置信的细微错误。