# 5.4 定时器中断

Xv6使用定时器中断来维持其时钟，并使其能够在受计算量限制的进程（compute-bound processes）之间切换；`usertrap`和`kerneltrap`中的`yield`调用会导致这种切换。定时器中断来自附加到每个RISC-V CPU上的时钟硬件。Xv6对该时钟硬件进行编程，以定期中断每个CPU。

RISC-V要求定时器中断在机器模式而不是管理模式下进行。RISC-V机器模式无需分页即可执行，并且有一组单独的控制寄存器，因此在机器模式下运行普通的xv6内核代码是不实际的。因此，xv6处理定时器中断完全不同于上面列出的陷阱机制。

机器模式下执行的代码位于`main`之前的***start.c***中，它设置了接收定时器中断（***kernel/start.c***:57）。工作的一部分是对CLINT（core-local interruptor）硬件编程，以在特定延迟后生成中断。另一部分是设置一个scratch区域，类似于trapframe，以帮助定时器中断处理程序保存寄存器和CLINT寄存器的地址。最后，`start`将`mtvec`设置为`timervec`，并使能定时器中断。

计时器中断可能发生在用户或内核代码正在执行的任何时候；内核无法在临界区操作期间禁用计时器中断。因此，计时器中断处理程序必须保证不干扰中断的内核代码。基本策略是处理程序要求RISC-V发出“软件中断”并立即返回。RISC-V用普通陷阱机制将软件中断传递给内核，并允许内核禁用它们。处理由定时器中断产生的软件中断的代码可以在`devintr` (***kernel/trap.c***:204)中看到。

机器模式定时器中断向量是`timervec`（***kernel/kernelvec.S***:93）。它在`start`准备的scratch区域中保存一些寄存器，以告诉CLINT何时生成下一个定时器中断，要求RISC-V引发软件中断，恢复寄存器，并且返回。定时器中断处理程序中没有C代码。