/*
  * Ok, we have a good vm_area for this memory access, so
  * we can handle it..
  */
good_area:
 write = error_code & PF_WRITE;

 /*访问权限不够则通过bad_area_access_error()处理,该函数是对__bad_area()的封装,只不过
   发送给用户进程的信号为SEGV_ACCERR*/
 if (unlikely(access_error(error_code, write, vma))) {
  bad_area_access_error(regs, error_code, address);
  return;
 }

 /*
  * If for any reason at all we couldn't handle the fault,
  * make sure we exit gracefully rather than endlessly redo
  * the fault:
  */
  /*分配新的页表和页框*/
 fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);

 if (unlikely(fault & VM_FAULT_ERROR)) {
  mm_fault_error(regs, error_code, address, fault);
  return;
 }

 if (fault & VM_FAULT_MAJOR) {
  tsk->maj_flt++;
  perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
         regs, address);
 } else {
  tsk->min_flt++;
  perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
         regs, address);
 }

 check_v8086_mode(regs, address, tsk);

 up_read(&mm->mmap_sem);
}
 
  bad_area()函数的主体函数为__bad_area()-->__bad_area_nosemaphore(),这个函数在上一篇博文中分析了其对内核的非法访问的处理,现在看其对用户空间的非法访问的处理

__bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
         unsigned long address, int si_code)
{
 struct task_struct *tsk = current;

 /* User mode accesses just cause a SIGSEGV */
 /*错误发生在用户态,则向用户进程发送一个SIGSEG信号V*/
 if (error_code & PF_USER) {
  /*
   * It's possible to have interrupts off here:
   */
  local_irq_enable();

  /*
   * Valid to do another page fault here because this one came
   * from user space:
   */
  if (is_prefetch(regs, error_code, address))
   return;

  if (is_errata100(regs, address))
   return;

  if (unlikely(show_unhandled_signals))
   show_signal_msg(regs, error_code, address, tsk);