Linux缺页异常处理

欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入

* 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_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);

/* 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页表项对应的物理页的不同状态来做各种不同的处理,具体的分析以后再给出。

[1][2]

肯承认错误则错已改了一半

Linux缺页异常处理

相关文章:

你感兴趣的文章:

标签云: