中断和异常

时间:2020-03-06 14:38:32  来源:igfitidea点击:

我在这里看到了几个有关异常的问题,其中一些暗示中断是异常,但没有一个使连接清晰。

  • 什么是中断?
  • 有什么例外? (请解释一下我们所知道的每种语言的例外情况,因为存在一些差异)
  • 什么时候例外是中断,反之亦然?

-亚当

解决方案

中断是由硬件或者特定的CPU指令生成的CPU信号。这些导致中断处理程序被执行。来自I / O硬件的I / O信号之类的事物会产生中断。

异常可以看作是Interupt的软件版本,仅影响其过程。

我不确定确切的细节,但是中断可能会导致异常。

当我们谈论中断和异常时,我们通常是在谈论硬件级别的代码,而中断和异常通常部分地由硬件实现,而部分地由软件实现。

中断是硬件中的事件(或者在组装中手动触发),该事件与可用于处理中断事件的处理程序向量相关联,可以是IO完成,IO错误(磁盘内存故障),IO事件(鼠标移动)例如)。当某些意外中断发生时,中断通常会引发异常。

异常是意外行为,通常在使用硬件时,这些异常来自中断,并在软件中使用中断处理程序进行单独处理。我们所看到的编程语言几乎总是将其伪装成某种控制结构。

通常,中断是某种硬件实现的陷阱。我们注册一个特定中断的处理程序(除以0,外围设备上的可用数据,计时器到期),并且当该事件发生时,所有系统范围内的中断都将停止,我们将快速处理该中断,然后一切继续。这些通常被强加在设备驱动程序或者内核中。

异常是一种软件实现的方式,用于处理代码中的错误。我们可以为特定(或者一般)异常设置处理程序。发生异常时,语言运行时将开始展开堆栈,直到到达该特定处理程序的处理程序为止。那时,我们可以处理异常,然后继续执行或者退出程序。

中断基本上是由硬件驱动的,例如打印机指示其"缺纸"或者网卡指示其已断开连接。

异常只是程序中的一个错误情况,由try / catch块检测到。喜欢:

Try
   {
   ... various code steps that "throw exceptions" on error ...
   }
catch (exception e)
   {
   print 'Crap! Something bad happened.' + e.toString()
   }

这是捕获在代码块中发生的"任何错误"的便捷方法,因此我们可以以类似的方式处理它们。

预计中断会定期发生(尽管有时它们是不定期的)..它们会中断CPU,因为发生了重要的事情,需要立即进行处理。

异常应该被认为是规则的异常。这些是由软件抛出的,因为发生了意外情况,这是我们尝试对此进行处理的机会,或者至少是优雅地崩溃。

我将详细说明什么是中断,因为有一种关键类型的中断尚未有人处理:计时器。

但是首先,让我备份。当我们收到中断时,中断处理程序(位于内核空间中)将运行,通常会禁用中断,查看所有待处理的业务(处理刚到达网络的数据包,处理按键等),然后(记住此时仍处于内核中)找出下一步应该运行的进程(可以是相同的进程,可以是不同的进程,取决于调度程序),然后运行它。

在任何给定时间,只有一个进程在处理器上运行。当我们使用多任务操作系统时,它在它们之间进行切换的方式称为上下文切换,基本上是将处理器的寄存器转储到内存中,流传递到新进程,并且当进程完成时,我们将上下文切换到其他。

因此,假设我编写了一个简单的C程序,该程序可以对所有数字,斐波那契数列或者其他任何事物进行计数而不会停止。甚至更好:除了在while(1)循环内旋转外,什么也不做。系统上的其他进程如何获得运行的机会?如果没有任何事情引起中断怎么办?

答案是我们有一个不断中断的计时器设备。这就是防止旋转过程破坏整个系统的原因。尽管我会注意到中断处理程序会禁用中断,但是如果我们执行无限期阻止的操作,则可以关闭整个系统。

例外

例外是处理器执行不在其正常路径上的代码。这是正常操作的"例外",它本质上是通过代码和控制结构进行线性移动。不同的语言支持各种类型的异常,这些异常通常用于处理程序操作期间的错误。

打断

中断是硬件级别的异常(通常)。中断是处理器中的物理信号,它告诉CPU存储其当前状态并跳转到中断(或者异常)处理程序代码。处理程序完成后,原始状态将恢复,并且处理可以继续。

中断始终是一个例外,即使是有意的也是如此。中断可能表明:

  • 错误,例如内存访问冲突
  • OS需要执行某种操作来支持正在运行的程序的操作,例如软件中断或者内存分页请求
  • 硬件设备需要注意,例如接收到的网络数据包或者空的发送缓冲区

这些总是迫使处理器暂停其当前活动以处理引发的异常,仅在中断处理程序完成后才恢复。

陷阱

在中断方面,常见的陷阱是比赛条件。例如,我们可能有一个中断,该中断会定期增加全局实时时钟。在32位计算机上,时钟可能是64位。

如果程序正在读取时钟并获取第一个32位字,则将发生中断,一旦中断处理程序退出,进程将获取第二个32位字,并且数据将不一致,这两个字可能不同步。如果尝试使用互斥量或者信号量在进程中锁定变量,则中断将挂起以等待锁定并暂停系统(死锁),除非处理程序和使用数据的进程都非常仔细地编写了。编写中断时很容易遇到麻烦。

重入函数也是另一个问题。如果要在程序代码中执行funcA,请执行一个也会执行funcA的中断,由于共享变量(静态变量或者堆变量,类等),最终可能会导致意想不到的后果。通常,我们通常希望在中断处理程序中执行尽可能少的代码,并经常将其设置一个标志,以便该进程以后可以进行实际工作而不必担心冲突。

在某些方面,这类似于为多处理器开发,这也是为什么内核编程仍然被许多人视为黑魔法的原因之一。

-亚当

处理器将具有许多外部中断引脚。通常,这些引脚连接到硬件,并用于指示何时发生某些外部事件。例如,如果我们使用的是串行端口,则UART将使引脚升高,该引脚连接到处理器上的一个中断引脚,以指示已接收到一个字节。

其他外设,例如计时器,USB控制器等,也会基于某些外部事件而产生中断。

当处理器在其外部中断引脚之一上接收到信号时,它将立即跳至内存中的指定位置并开始执行。执行的代码通常称为ISR或者中断服务程序。除非我们实现驱动程序或者做某种嵌入式软件,否则我们不太可能会遇到ISR。

不幸的是,关于异常的问题的答案还不太清楚,此页面上的其他答案中列出了3种不同的含义。

罗恩·萨维奇(Ron Savage)的答案是指软件构造。这纯粹是应用程序级别的异常,其中一段代码能够指示可以由其他某些段代码检测到的错误。这里根本不涉及硬件。

然后是任务看到的异常。这是一个操作系统级别的构造,用于在执行非法操作(例如除以0,非法访问内存等)时终止任务。

第三,存在硬件异常。就行为而言,它与中断相同,因为处理器将立即跳转到某些指定的内存位置并开始执行。异常与中断的区别在于异常是由处理器检测到的某些非法活动引起的。例如,处理器上的MMU将检测到非法的内存访问并导致异常。这些硬件异常是操作系统执行其清理任务的初始触发器(如上段所述)。

中断由CPU外部的设备生成(定时器滴答,磁盘操作完成,网络数据包到达等),并且与程序执行异步。异常与程序执行同步(例如被零除,访问无效地址)。

除非程序在没有操作系统的情况下执行(或者正在开发操作系统),否则它将永远不会看到原始异常/中断。它们被操作系统捕获并由它进行处理(中断),或者在转换回用户程序之前(例如,UNIX上的信号,Windows上的结构化异常处理(SEH))被转换为某种其他形式,然后才可以被操作系统处理。它。

保持简单...

处理完中断后,我们(通常)会返回到被中断之前的操作。

处理异常涉及扔掉我们当前正在处理的连续层,直到我们冒泡到可以处理(捕获)异常的地步为止。

在处理中断时,我们可以决定引发异常,但这并不意味着我们必须将中断本身视为异常。异常不会"中断"(因为这意味着可能会返回到被中断之前的状态);而是他们"中止"了我们当前活动(的一部分)。

而且,正如已经多次提到的那样,中断通常是由外部实体(例如硬件或者用户)(例如,鼠标单击或者CTRL-C之类的按键)触发的,而异常是由软件检测到"问题"或者"特殊情况"。

中断表明处理器内核外部的某些内容需要引起注意。它中断程序的正常流程,执行中断服务程序(ISR),通常返回到中断发生之前的位置。

这个基本主题有很多变化:中断可能是由软件生成的,另一个任务可能是在ISR之后获得CPU等。关键点在于,由于代码/ CPU没有中断,中断可以随时发生掌控。

定义异常有点棘手,因为它可能具有三个含义级别:

硬件异常

某些处理器(例如PowerPC)定义异常以指示某种异常情况已经发生:系统重置,无效地址,某些虚拟地址转换高速缓存未命中,等等。

这些异常也用于实现断点和系统调用。在这种情况下,它们的行为几乎就像中断一样。

操作系统异常

某些硬件异常将由操作系统处理。例如,程序访问无效的内存。这将导致硬件异常。操作系统具有针对该异常的处理程序,并且很有可能操作系统会向应用程序(例如SIGSEGV)发送信号,表明存在问题。

如果程序安装了信号处理程序,则该信号处理程序将运行并有望处理该情况。如果我们没有信号处理程序,则该程序可以终止或者挂起。

我认为窗口的结构化异常处理程序(SEH)是这种类型的异常。

软件异常

诸如Java,C ++和Chave之类的某些语言是软件异常的概念,其中的语言提供了与程序操作相关的不可预见或者异常情况的处理。在这种情况下,在代码中的某个位置会引发异常,并且程序执行堆栈中更高级别的某些代码将"捕获"异常并执行。这就是try / catch块的作用。