/* Kernel addresses are always protection faults: */
  tsk->thread.cr2  = address;
  tsk->thread.error_code = error_code | (address >= TASK_SIZE);
  tsk->thread.trap_no = 14;

  force_sig_info_fault(SIGSEGV, si_code, address, tsk);

  return;
 }
 ...
 ...
}
 
  在确定了这次异常是因为物理页没分配而导致后,通过good_area路径来处理,可想而知,该路径在确定了访问权限足够后,将完成页表和物理页的分配,这个任务有handle_mm_fault()函数来完成


int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
  unsigned long address, unsigned int flags)
{
 pgd_t *pgd;
 pud_t *pud;
 pmd_t *pmd;
 pte_t *pte;

 __set_current_state(TASK_RUNNING);

 count_vm_event(PGFAULT);

 if (unlikely(is_vm_hugetlb_page(vma)))
  return hugetlb_fault(mm, vma, address, flags);

 pgd = pgd_offset(mm, address);
 pud = pud_alloc(mm, pgd, address);//分配pud目录
 if (!pud)
  return VM_FAULT_OOM;
 pmd = pmd_alloc(mm, pud, address);//分配pmd目录
 if (!pmd)
  return VM_FAULT_OOM;
 pte = pte_alloc_map(mm, pmd, address);//分配pte表
 if (!pte)
  return VM_FAULT_OOM;

 /*handle_pte_fault()的任务是为pte绑定新的页框,它会根据pte页表项的情况来做不同的处理*/
 return handle_pte_fault(mm, vma, address, pte, pmd, flags);
}
 
  handle_pte_fault()函数的处理比较复杂,因为它要根据pte页表项对应的物理页的不同状态来做各种不同的处理,具体的分析以后再给出。