ISR和函数调用有什么区别?

8
我想了解ISR(中断服务例程)和函数调用之间的区别。
从硬件角度来看,我认为函数调用和ISR是相同的。如果我错了,请纠正我。关于ISR和函数调用,我找到的所有信息如下:
ISR:
- 异步事件,在程序执行期间任何时候都可能发生 - 在堆栈上保存PC、标志和寄存器,并禁用所有中断并加载ISR的地址 - ISR不能有可以传递给它的参数 - 无法返回值 - 启用中断 - 通常很小,因为它们正在占用其他进程的时间 - 一些ISR有自己的堆栈
函数:
- 每当有函数调用时发生 - 在堆栈上保存PC和寄存器 - 可以有参数 - 可以返回值 - 对执行的大小和持续时间没有限制
除此之外还有什么区别吗?请告诉我。我还读过关于从ISR调用函数的内容,请详细说明。
4个回答

4
因此,你已经确认它们是相同的,接下来列出了它们不同的方式 - 这可能更能回答你的问题。
关于ISR的前四点是广泛而普遍的真实性。关于启用中断的观点并非必然如此,这是程序员的实现决策,并且可能由架构确定,并且小是一个指导方针而不是要求 - “小”完全是主观的。
它们的区别不在于它们如何编码(尽管ISR通常会施加许多限制,并且可能具有普通函数所没有的特权),而是在于它们的调用方式和处理器的行为。
函数(或更一般地说,过程或子例程)必须明确调用,并且是与其调用者相同的上下文和执行线程的一部分。硬件ISR不是显式调用,而是由某些外部事件调用(对于处理器核心来说是外部的 - 芯片上的外设可能会生成中断)。当调用中断时,在切换到ISR的上下文之前自动保存当前线程的上下文。返回时,反向上下文切换发生,还原处理器在中断之前的状态,以便从中断点继续执行。
通过多线程操作系统或调度程序的存在,该机制可能变得复杂,因为ISR本身可能会引起线程上下文切换,以便从ISR返回时会切换到不同的执行线程或上下文。在这种情况下,此类机制由操作系统管理。
某些处理器支持另一种类型的ISR - 软件中断。软件中断类似于函数调用,因为它是由指令显式调用而不是单个事件调用,但提供了一个间接机制,使调用者不需要知道ISR的地址,实际上该地址可能会更改。在这种意义上,它与通过指针调用函数几乎没有区别,但因为它是ISR,所以在中断上下文中运行,而不是在调用者的上下文中运行,因此可能具有正常函数没有的限制和特权。
基本上,中断能够直接且确定地响应事件,否则你可能会轮询或测试事件然后处理它,但只能在你选择测试它的时间而不是在其实际发生时处理它,这可能是可变和无法接受的长时间。

2
主要区别在于中断处理程序通常是由外围硬件调用的-外围设备生成一个实际的硬件信号,处理器中的硬件将控制权转移到适当的处理程序,而不需要运行中断之前的代码执行任何操作。与函数不同,没有调用-处理器硬件通过中断从中断代码中撕走执行。
在支持多线程/进程的操作系统上,函数调用发生在与调用方相同的进程/线程上下文中。然而,中断没有线程或进程上下文-由后台BitTorrent下载引起的网络中断可能会在您编辑Word文档时发生,因此处理程序在其所绑定的进程/线程拥有的预分配缓冲区之间加载数据,可以发出信号量,可能能够设置操作系统事件标志。就这些了。
通常,中断处理程序直接执行中断返回,因此允许执行被中断的代码而没有任何进一步的干扰。在像8051这样的简单控制器上,它通常在没有复杂操作系统的情况下运行嵌入式代码时,这是唯一可行的选择。对于具有抢占式多线程操作系统的系统,中断处理程序还可以通过操作系统代码执行其中断返回,从而导致调度程序运行。这使得中断处理程序可以使等待中断的线程准备就绪,并且可能正在运行(因此可能抢占最初被中断的线程)。这使得此类系统可以具有良好的I/O性能,而无需进行任何轮询。
硬件中断源可能是嵌入在处理器芯片中的外围设备-网络控制器、磁盘控制器、显示控制器、DMA控制器、USB控制器、互核通信控制器(在具有多个核心的处理器上),定时器等,或者包装上的中断请求引脚可以用于从外部硬件源生成中断(可能是按钮、键盘、键盘或触摸屏硬件)。

1
他们不一定与您在ISR的第一个要点中所述的相同:中断是异步的,因此必须以某种方式“中断”主处理器的工作。
例如,让我们看一下这个带有地址的MIPS代码,它不会做任何有用的事情:
4000.       add $1, $2, $3
4004.       sw $ra, 0($sp)
4008.       jal subr   # function call, sets $ra to 4012 and jumps to 4024
4012.       lw $ra, 0($sp)
4016.       jr $ra
4020.
4024. subr: sub $2, $1, $3
4028.       jr $ra

这段代码可以从主处理器中处理:算术操作(第1行,第7行)由算术单元完成,内存访问(第2行,第4行)由内存控制器完成,跳转(第3行、第5行、第8行)也由主CPU完成。(jal的实际地址在对象文件绑定期间设置。)

这是用于函数调用的。随时确定代码当前所在位置以及下一个执行点上执行的代码(即当程序计数器增加时:PC+=4)。

现在出现了这样一种情况,当您的函数执行某些复杂操作时,但仍希望软件对按键作出反应。然后就会出现所谓的协处理器。该协处理器等待某些事件(例如键盘上的按键),然后调用中断处理程序。这是位于内存中特定地址上的一块代码。

想象一下,处理器正在进行上述计算,但同时您想要将按键次数存储在地址keys上。然后,您编写一个从地址0x80000180开始的程序(这被定义为MIPS中的异常处理程序地址):

lw $at, keys
addi $at, $at, 1
sw $at, keys
eret

现在,按下一个键会发生什么?

  1. 协处理器意识到按键
  2. 主处理器的当前PC被保存
  3. 将主处理器的PC设置为0x80000180,执行中断代码
  4. eret上,PC被设置为中断发生前主处理器的PC
  5. 主程序的执行在那里继续。

在步骤2和3之间,从4到5再次切换到正常执行到中断处理。

注意:我简化了很多内容,但应该清楚,中断与函数调用不同,并且硬件必须具有额外的能力进行中断处理。


很遗憾,我无法提供关于此的在线资源,因为这需要计算机系统的书面脚本 ;) - contradictioned
那么这是否意味着像8051这样的微处理器或8091微控制器这样没有协处理器的设备将具有相同的中断和函数调用?请帮帮我,我真的很困惑。 - Nilesh Agrawal
1
我不是微控制器方面的专家,但在这个网站上有一个8051的框图:http://aninditadhikary.wordpress.com/tag/intel-8051/,您可以看到“中断控制器”,它位于CPU旁边,类似于MIPS协处理器。 - contradictioned
这里有一个关于8051中断的教程:http://www.8052.com/tutint.phtml。要点是:CPU在每行“正常”代码之后检查是否有异常,如果有,它会跳转到异常处理程序。 - contradictioned

1

以上回答基本上已经很完整了...特别要注意Clifford提到的软件中断。

我想补充的是,函数调用时保存在寄存器上下文中的内容是由CPU架构的过程调用约定定义的。这通常意味着调用者将一些内容保存在堆栈上,被调用者也保存一些内容,基本上是一个静态集合。例外:IA64具有动态的寄存器保存/恢复窗口。

在ISR中,存储的寄存器上下文只是将在ISR中使用的内容。如果使用一个寄存器,那么只有该寄存器被保存/恢复。

在大多数cpu上,由于过程调用约定的静态特性,在函数调用中存储/恢复的寄存器集比在ISR中存储/恢复的寄存器集要大得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接