8

我想了解 ISR(中断服务程序)和函数调用之间的区别。

从硬件的角度来看,我觉得函数调用和 ISR 都是一样的。如果我错了,请纠正我。我能找到的关于 ISR 和函数调用的所有信息如下:

情监侦:

  • 程序执行过程中随时可能发生的异步事件

  • 将 PC、标志和寄存器保存在堆栈上并禁用所有中断并加载 ISR 的地址

  • ISR 不能有可以传递给它的参数

  • 无法返回值
  • 启用中断
  • 通常很小,因为他们正在花费一些其他过程的时间
  • 一些 ISR 有自己的堆栈

功能:

  • 每当有函数调用时发生

  • 将 PC 和寄存器保存在堆栈中

  • 可以有论据

  • 可以返回值

  • 对执行的大小和持续时间没有限制

除此之外还有什么不同吗?请告诉我。我还阅读了有关 ISR 的函数调用是如何发生的。请在上面突出显示。

4

4 回答 4

4

因此,在断言它们是相同的之后,您继续列出它们不同的方式——这也许更能回答您的问题。

您关于 ISR 的前四点大体上是正确的。关于启用中断的点不一定是这种情况,是程序员的实现决定,可能由架构决定,小​​是指导方针而不是要求——“小”完全是主观的”。

差异并不在于它们的编码方式(尽管 ISR 通常会施加许多限制,并且可能还具有普通函数没有的特权),而在于它们的调用方式和处理器的行为。

必须显式调用函数(或更一般的过程或子例程),并且与其调用者属于同一上下文和执行线程。硬件 ISR 没有被显式调用,而是由一些外部事件调用(在处理器内核之外 - 片上外围设备可能会产生中断)。当调用中断时,在将上下文切换到 ISR 之前会自动保留当前线程的上下文。返回时,发生反向上下文切换,恢复中断前处理器的状态,以便从中断点继续执行。

该机制可能因多线程操作系统或调度程序的存在而变得复杂,由此 ISR 本身可能会导致线程上下文切换,以便在从 ISR 返回时切换到不同的执行线程或上下文。此类机制是受管理的在这种情况下由操作系统。

某些处理器还支持另一种 ISR——软件中断。软件中断的使用类似于函数调用,因为它是由指令而不是单个事件显式调用的,但它提供了一种间接机制,调用者不需要知道 ISR 的地址,而且实际上该地址可能会改变. 从这个意义上说,它与通过指针调用函数几乎没有什么不同,但由于它是一个 ISR,它在中断上下文中运行,而不是在调用者的上下文中运行,因此可能具有普通函数没有的限制和特权。

从根本上说,中断能够直接和确定性地响应事件,否则您可能会轮询或测试事件然后处理它,但只能在您选择测试它而不是在它实际发生时处理它,这可能是可变且长得令人无法接受。

于 2013-07-21T10:04:53.063 回答
2

主要区别在于,中断处理程序(通常)由外围硬件调用——实际的硬件信号由外围设备生成,处理器中的硬件将控制权转移到适当的处理程序,而中断之前运行的代码没有任何动作. 与函数不同,没有调用——处理器硬件将执行从中断的代码中剥离出来。

在支持多线程/进程的操作系统上,函数调用发生在与调用者相同的进程/线程上下文中。OTOH 中断没有线程或进程上下文 - 在您编辑 Word 文档时可能会发生由后台 BitTorrent 下载导致的网络中断,因此处理程序的功能非常有限。它可以将数据加载到/从属于它所绑定的进程/线程的预分配缓冲区,它可以发出信号量,它可能能够设置操作系统事件标志。就是这样。

通常,中断处理程序直接执行中断返回,因此允许中断代码的执行在没有任何进一步干扰的情况下继续执行。在更简单的控制器上,如 yopur 8051,通常在没有复杂操作系统的情况下运行嵌入式代码,这是唯一可用的课程。对于抢占式多线程操作系统,中断处理程序具有通过操作系统代码执行其中断返回并因此导致调度程序运行的附加选项。这允许中断处理程序使等待中断的线程准备好并可能运行(因此可能抢占最初被中断的线程)。这允许此类系统在没有任何轮询的情况下具有良好的 I/O 性能。

硬件中断源可以是嵌入在处理器芯片中的外围设备 - 网络控制器、磁盘控制器、显示控制器、DMA 控制器、USB 控制器、内核间通信控制器(在具有多个内核的处理器上)、定时器等或中断请求引脚/封装上的 s 可用于从外部硬件源(可能是按钮、键盘、小键盘或触摸屏硬件)生成中断。

于 2013-07-21T09:16:25.907 回答
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)。

现在重点来了,当你的函数做了一些复杂的事情,但你仍然希望软件对击键做出反应时。然后一个所谓的协处理器开始发挥作用。这个协处理器一直等到某个事件(如键盘上的击键)发生,然后调用中断处理程序。这是位于内存中某个地址的代码块。

想想,处理器在上面的计算中,但同时你想在 address 上存储击键次数keys。然后你编写一个从地址开始的程序0x80000180(这在 MIPS 中定义为异常处理程序地址):

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

现在击键会发生什么?

  1. 协处理器知道击键
  2. 保存主处理器当前PC
  3. 主处理器的PC设置为0x80000180,执行中断代码
  4. eretPC 上设置为中断发生前主处理器的 PC
  5. 主程序的执行在那里继续。

这里在第 2 步和第 3 步之间从正常执行切换到中断处理,然后从第 4 步到第 5 步。

注意:我已经简化了很多,但应该清楚的是,中断与函数调用有何不同,以及硬件如何必须具有额外的中断处理能力。

于 2013-07-21T01:24:04.597 回答
1

上面的答案非常完整......特别注意克利福德的软件中断。

我要做的唯一补充就是这个。存储在函数调用中的寄存器上下文由 CPU 体系结构的过程调用约定定义。这通常意味着调用者将一些东西保存在堆栈上,而被调用者保存一些东西并且几乎是一个静态集合。例外:具有寄存器保存/恢复的动态窗口的 IA64。

在 ISR 上,唯一存储的寄存器上下文是将在 ISR 中使用的内容。如果使用一个寄存器,则仅保存/恢复该寄存器。

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

于 2013-08-13T20:40:16.010 回答