# 第四章 陷阱指令和系统调用

有三种事件会导致中央处理器搁置普通指令的执行，并强制将控制权转移到处理该事件的特殊代码上。一种情况是系统调用，当用户程序执行`ecall`指令要求内核为其做些什么时；另一种情况是异常：（用户或内核）指令做了一些非法的事情，例如除以零或使用无效的虚拟地址；第三种情况是设备中断，一个设备，例如当磁盘硬件完成读或写请求时，向系统表明它需要被关注。

本书使用陷阱（trap）作为这些情况的通用术语。通常，陷阱发生时正在执行的任何代码都需要稍后恢复，并且不需要意识到发生了任何特殊的事情。也就是说，我们经常希望陷阱是透明的；这对于中断尤其重要，中断代码通常难以预料。通常的顺序是陷阱强制将控制权转移到内核；内核保存寄存器和其他状态，以便可以恢复执行；内核执行适当的处理程序代码（例如，系统调用接口或设备驱动程序）；内核恢复保存的状态并从陷阱中返回；原始代码从它停止的地方恢复。

xv6内核处理所有陷阱。这对于系统调用来说是顺理成章的。由于隔离性要求用户进程不直接使用设备，而且只有内核具有设备处理所需的状态，因而对中断也是有意义的。因为xv6通过杀死违规程序来响应用户空间中的所有异常，它也对异常有意义。

Xv6陷阱处理分为四个阶段： RISC-V CPU采取的硬件操作、为内核C代码执行而准备的汇编程序集“向量”、决定如何处理陷阱的C陷阱处理程序以及系统调用或设备驱动程序服务例程。虽然三种陷阱类型之间的共性表明内核可以用一个代码路径处理所有陷阱，但对于三种不同的情况：来自用户空间的陷阱、来自内核空间的陷阱和定时器中断，分别使用单独的程序集向量和C陷阱处理程序更加方便。