内核缺页异常处理

来源:互联网 发布:人工智能假肢胳膊 编辑:程序博客网 时间:2024/05/09 11:49

在访问内核地址空间时,缺页异常可能被各种条件出发,如下所述:

  • 内核本身的程序设计错误导致访问不正确的地址,这个在稳定版本中永远不会发生,在开发版本中偶尔会发生
  • 内核通过用户空间传递的参数访问了无效地址
  • 访问使用vmalloc分配的区域,触发缺页异常

前两种情况是真正的错误,内核必须使用最后的手段---异常修正(exception fixup)机制来进行处理
vmalloc的情况是导致缺页异常的合理情况,必须加以校正。直至对应的缺页异常发生之前,vmalloc区域中的修改都不会传输到进程的页表中。因此在对vmalloc异常进行处理时,必须从主页表复制适当的访问权限信息到进程的页表中。

对于用户态发生的缺页异常,内核将使用按需调页机制,自动并透明地返回一个物理内存页;如果访问发生在内核态,则必须使用不同的手段进行校正。每次发生缺页异常时,将输出异常的原因和当前执行代码的地址。这使得内核可以编译一个列表,列出所有可能执行未授权内存访问操作处理(异常处理)的代码块。这就是"异常表"。

struct exception_table_entry {     unsigned long insn, fixup;};

insn: 指定了内核在虚拟地址空间发生异常的位置
fixup:指定了进行异常处理代码的地址

fixup_exception用于搜索异常表:

int fixup_exception(struct pt_regs *regs){     const struct exception_table_entry *fixup;#ifdef CONFIG_PNPBIOS     if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {          extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;          extern u32 pnp_bios_is_utter_crap;          pnp_bios_is_utter_crap = 1;          printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");          __asm__ volatile(               "movl %0, %%esp\n\t"               "jmp *%1\n\t"               : : "g" (pnp_bios_fault_esp), "g" (pnp_bios_fault_eip));          panic("do_trap: can't hit this");     }#endif     fixup = search_exception_tables(regs->ip);     if (fixup) {          regs->ip = fixup->fixup;          return 1;     }     return 0;}

regs->ip指向EIP寄存器,在IA32处理器上包含了出发异常的代码段地址。
当找到修正例程时,将指令指针设置到对应的内存位置。因此,在fixup_exception通过return返回时,内核将执行找到的异常处理程序。
如果没找到异常处理程序(修正例程),则表明出现了一个真正的内核异常,在对search_exception_tables调用不成功后,将跳转到do_page_fault中相应的异常标号处,最终将导致内核进入oops状态。


0 0
原创粉丝点击