//regs 发生异常时寄存器的值
//error_code 5位的值,第3位标志异常发生在内核态还是用户态
do_page_fault函数:
{
//获得产生缺页异常的地址,该地址保存在cr2寄存器
address = read_cr2();
//检查线性地址是否属于第4个G
//如果内核访问不存在的内存页框,则执行vmalloc_fault
//该部分代码处理可能由于在内核态访问非连续内存区而引起的缺页
跨过一部分检测
//接下来,检查异常发生时,是否正在执行一些关键例程或正在执行内核线程
//假设缺页没有发生在中断处理,可延迟函数,临界区或者内核线程中
//检查进程的线性区以决定引起缺页的线性地址是否包含在进程的地址空间中
//获得mmap_sem信号量
//查找发生异常的地址所属的vma
//如果vma为空,说明address这后没有线性区,因此这个地址肯定是无效的
//如果address之后的第一个线性区包含address,则跳到good area处理
//以上两者都不成立,则可能是用户态栈上的Push或pusha操作引起的
//栈映身到线性区上的话,该vma被标志为VM_GROWSDOWN
//expand_stack扩展进程地址空间的栈
//接着执行handle_mm_fault处理缺页异常
}