中断(Interrupt)

问题:什么是中断?为什么需要中断?中断是如何产生的?操作系统中是如何处理中断的?

​ –解答:和page fault一样,中断也会引起trap机制。当发生中断时,系统需要停止当前运行的工作,优先处理中断事件。在操作系统中主要有3类中断:由软件引起的中断、时钟中断(用于时间片调度算法)以及外部设备引起的中断(比如网卡受到一个packet后,在某个时间点会产生中断将处理完的packet交给操作系统)。在本节主要介绍最后一种中断。

​ 在计算机中为了提高运行效率,几乎所有外部设备和CPU都是并行运行的,这样做的好处是可以充分利用CPU资源。因此当外部设备准备好了后(一些资源的初始化操作),必须依靠某种机制使它们能够和CPU进行交互。这种机制就是中断,它们会产生一个中断,告诉操作系统我需要CPU。

​ 当产生中断时,我们需要在内核处理这些中断,因此会触发trap机制完成到内核的切换以及保存好那些重要的用户数据,这个过程在之前讲过,这里不再赘述。在操作系统中设置了PLIC(Platform Level Interrupt Control)用于将这些中断分发给CPU。更具体的流程是在PLIC中会存储大量中断信息,并且会通知CPU有这些中断需要处理,当某个CPU接收中断时,PLIC会将中断传送给CPU,CPU处理完后会通知PLIC,PLIC会清除掉已处理的中断信息。

image-20240319135551515

问题:和System Call以及page fault相比,外设中断有什么区别?

​ –解答:当硬件生成中断时,Interrupt handler与当前运行的进程在CPU上没有任何关联。但如果是系统调用的话,系统调用发生在运行进程的context下。

​ 我们还需要对这些外部设备进行编程,以告诉它们在读写某个控制寄存器时,需要做出何种反应。

​ 最后,外部设备和CPU是并行运行的,在之前也讲到过,这是提升CPU使用的一种方法。

问题:什么是设备驱动?

​ –解答:所谓设备驱动就是管理设备的代码,一般由top和bottom两部分组成,bottom中编写的是Interrupt Handler的逻辑,当CPU处理某个设备的中断时,它会执行这部分代码。top部分提供了一些接口用于与其他进程进行交互(由于Interrupt Handler不依赖任何一个进程的context,因此其他进程无法知道Interrupt Handler的地址)。在top和bottom之间通过一个队列buffer进行通信,Interrupt Handler向buffer中写入数据,top从buffer中读取数据。

问题:如何对外部设备进行编程?

​ –解答:这些外部设备地址通常位于内存中某个特定区间,这由硬件开发人员决定,操作系统需要知道这些设备的地址,然后直接使用load/store指令修改其中的内容。以下是SiFive主板上的一些设备地址

image-20240324093129416

可以发现0x0C00_0000~0x0FFF_FFFF这部分地址分配给了PLIC设备

问题:和处理中断相关的寄存器有哪些?分别有什么作用?

​ –解答:

  • SIE(Supervisor Interrupt Enable)寄存器。这个寄存器中有一个bit(E)专门针对例如UART的外部设备的中断;有一个bit(S)专门针对软件中断,软件中断可能由一个CPU核触发给另一个CPU核;还有一个bit(T)专门针对定时器中断。我们这节课只关注外部设备的中断。
  • SSTATUS(Supervisor Status)寄存器。这个寄存器中有一个bit来打开或者关闭中断。每一个CPU核都有独立的SIE和SSTATUS寄存器,除了通过SIE寄存器来单独控制特定的中断,还可以通过SSTATUS寄存器中的一个bit来控制所有的中断。
  • SIP(Supervisor Interrupt Pending)寄存器。当发生中断时,处理器可以通过查看这个寄存器知道当前是什么类型的中断。
  • SCAUSE寄存器,这个寄存器我们之前看过很多次。它会表明当前状态的原因是中断。
  • STVEC寄存器,它会保存当trap,page fault或者中断发生时,CPU运行的用户程序的程序计数器,这样才能在稍后恢复程序的运行。

问题:xv6系统中是如何实现中断的?