两种缺页异常的情况:错误编程和属于地址空间但是还没有分配页框的所引起的
do_page_fault第一步操作时读取引起缺页的线性地址,这个地址保存在address局部变量中:
首先判断是否在内核空间(即检查缺页的线性地址是否属于第4G,是的话goto vmalloc_fault,处理因在内核态访问一个非连续内存而引起的错误)
然后看cpu是否在执行中断或者执行内核进程
如果不是,再判断是否在线性区中
在线性区中的,跳到good_area,而不在线性区中,跳到bad_area,当然有例外,因为栈的伸展而导致的线性区的增大,expand_stack()也是good_area.
如果address不在进程地址空间,发生在用户态,那么发送SIGSEGV信号
发生在内核态。。。。
补充一点:
栈如何映射到线性区:每个向低地址扩散的栈所在的区,它的VM_GROWDOWN标志被设置,这样vm_start减小,vm_end不变
通过系统调用sys_brk向内核申请一段虚地址空间vma来建立地址映射,vma全部建立起和内存页的映射
如果addr属于进程地址空间,那么看异常由什么访问权限引起,如果线性区的访问权限和引起异常的访问权限不匹配,那么到-〉bad_area
否则handle_mm_fault()分配一个新的页框。当然可能address映射的页中间目录和页表项不存在,还要给他分配呢
handle_pte_handle()关键!
检查address地址所对应页表项,看访问的页是否存在
如果不存在,那么就分配一个新的页框,请求调页
如果访问的也存在,但是标为只读,它已经存放一个页框中了,分配一个页框,并copy数据,COW