与中断不同,各种异常都具有固定的中断向量以及固定的异常服务程序(在 trap_init 函数中指定)。因
此,当异常发生时,将直接跳转到相应的服务程序并执行。
异常服务程序都定义在 arch/i386/kernel/entry.S 文件,比如堆栈段异常(中断向量 12)的服务程序即是:
中断发生时,会跳转到公共的服务程序 common_interrupt。异常也有类似的操作,只不过是跳转到汇编函数 error_code。
error_code 函数会调用真正的服务程序对异常进行处理。对于堆栈段异常,这个服务程序就是 957 行的 C 函数 do_stack_segment。
与中断有所不同的是,如果所发生的异常产生出错码,就将这个出错码也压入堆栈。而对于不产生出
错码的异常,则在进入 error_code 函数前补上一个。比如无效操作码异常(中断向量 6):
第 921 行的 0,即是出错码的替代品。
对异常处理完毕后,error_code 会调用汇编函数 ret_from_exception 从异常返回。
此,当异常发生时,将直接跳转到相应的服务程序并执行。
异常服务程序都定义在 arch/i386/kernel/entry.S 文件,比如堆栈段异常(中断向量 12)的服务程序即是:
955 ENTRY(stack_segment)
956 RING0_EC_FRAME
957 pushl $do_stack_segment
958 CFI_ADJUST_CFA_OFFSET 4
959 jmp error_code
960 CFI_ENDPROC
961 END(stack_segment)
中断发生时,会跳转到公共的服务程序 common_interrupt。异常也有类似的操作,只不过是跳转到汇编函数 error_code。
error_code 函数会调用真正的服务程序对异常进行处理。对于堆栈段异常,这个服务程序就是 957 行的 C 函数 do_stack_segment。
与中断有所不同的是,如果所发生的异常产生出错码,就将这个出错码也压入堆栈。而对于不产生出
错码的异常,则在进入 error_code 函数前补上一个。比如无效操作码异常(中断向量 6):
919 ENTRY(invalid_op)
920 RING0_INT_FRAME
921 pushl $0
922 CFI_ADJUST_CFA_OFFSET 4
923 pushl $do_invalid_op
924 CFI_ADJUST_CFA_OFFSET 4
925 jmp error_code
926 CFI_ENDPROC
927 END(invalid_op)
第 921 行的 0,即是出错码的替代品。
对异常处理完毕后,error_code 会调用汇编函数 ret_from_exception 从异常返回。