首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

缺页异常详解(4)

缺页异常详解(4)

如果当前执行流程在内核态,不论是在临界区(中断/推后执行/临界区)还是内核进程本身(内核的mmNULL),说明在内核态出了问题,跳到标号no_context进入内核态异常处理,由函数__do_kernel_fault完成,这个函数首先尽可能的设法解决这个异常,通过查找异常表中和目前的异常对应的解决办法并调用执行,这个部分的细节一直没有找到在哪里,如果找到的话留言告我一下吧!如果无法通过异常表解决,那么内核就要在打印其页表等内容后退出了!其源码如下
static void
__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
                     struct pt_regs *regs)
{
         /*
          * Are we prepared to handle this kernel fault?
          */
         /*fixup_exception()用于搜索异常表,并试图找到一个对应该异常的例程来进行修正,这个例程在fixup_exception()返回后执行*/
         if (fixup_exception(regs))
                   return;
         /*
          * No handler, we'll have to terminate things with extreme prejudice.
          */
         /*走到这里就说明异常确实是由于内核的程序设计缺陷导致的了,内核将产生一个oops,下面的工作就是打印CPU寄存器和内核态堆栈的信息到控制台并终结当前的进程*/
         bust_spinlocks(1);
         printk(KERN_ALERT
                   "Unable to handle kernel %s at virtual address %08lx\n",
                   (addr < PAGE_SIZE) ? "NULL pointer dereference" :
                   "paging request", addr);
         /*打印内核一二级页表信息*/
         show_pte(mm, addr);
         /*内核产生一个oops,打印一堆东西准备退出*/
         die("Oops", regs, fsr);
         bust_spinlocks(0);
         /*内核退出了!*/
         do_exit(SIGKILL);
}


接上一篇
回到函数do_page_fault,如果不是内核的缺页异常而是用户进程的缺页异常,那么调用函数__do_page_fault,这个应该是本文的重点,主要讨论的是用户进程的缺页异常,结合最前面说的用户进程产生缺页异常的四种情况,函数__do_page_fault都会排查到,源码如下
__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
                   struct task_struct *tsk)
{
         struct vm_area_struct *vma;
         int fault;
    /*搜索出现异常的地址前向最近的的vma*/
         vma = find_vma(mm, addr);
         fault = VM_FAULT_BADMAP;
    /*如果vmaNULL,说明addr之后没有vma,所以这个addr是个错误地址*/
         if (unlikely(!vma))
                   goto out;
    /*如果addr后面有vma,但不包含addr,不能断定addr是错误地址,还需检查*/
         if (unlikely(vma->vm_start > addr))
                   goto check_stack;
         /*
          * Ok, we have a good vm_area for this
          * memory access, so we can handle it.
          */
good_area:
    /*权限错误也要返回,比如缺页报错(由参数fsr标识)报的是不可写/不可执行的错误,但addr所属vma线性区本身就不可写/不可执行,那么就直接返回,因为问题根本不是缺页,而是vma就已经有问题*/
         if (access_error(fsr, vma)) {
                   fault = VM_FAULT_BADACCESS;
                   goto out;
         }
         /*
          * If for any reason at all we couldn't handle the fault, make
          * sure we exit gracefully rather than endlessly redo the fault.
          */
继承事业,薪火相传
返回列表