4.7.2 Linux缺页中断处理过程
进程在发生页面错误时,首先会调用do_page_fault函数,这个函数负责从CR2寄存器中取得发生页面错误的地址,然后根据从sys_call.s文件中得到的error_code来对错误进行分类,通过调用find_vma来找到发生页面错误的地址所在的vm_area_struct结构的指针。由于一个进程可以由多个vm_area_struct结构,因此Linux采用AVL树来管理这些结构。Linux的缺页错误主要由handle_mm_fault来处理。在handle_mm_fault中,首先为要映射到进程虚拟地址空间的页分配三级页表中相应的页表入口指针,然后调用真正处理页面错误的函数handle_pte_fault。
Handle_pte_fault函数处理的错误有三种:一是缺页错误且出错的页面还从未被映射到虚拟地址空间,针对这种页面错误它会调用函数do_no_page来进一步处理;二是缺页错误但是出错的页面曾经被映射到虚拟地址空间,也就是说这个页现在应该在swap cache中,则调用do_swap_page函数;三是页面写权限的错误,主要是进程向一个共享页面进行写操作的处理,当发生这种页面错误时,handle_pte_fault会调用do_wp_page函数来处理。
do_no_page函数中,如果发生页面错误的地址所在的vm_area_struct没有定义自己的nopage函数,则为这个页面申请一个新的页面并将可执行文件的映像调入内存,否则调用用户自定义的操作。如果发生错误的页面是可写的,则将页面直接置为可写且dirty,以免下次对这个页面进行写操作时再处理。
do_swap_page函数中主要将swap cache中的内容调入内存,如果用户没有自定义的swapin函数,则调用系统的swapin函数,否则调用用户自定义的函数。
do_wp_page函数处理的是向共享页面写的情况。Linux对这种情况的页面错误采取的是copy_on_write策略。当子进程创建之后,系统并不是把父进程的所有页面复制一份给子进程,而只是将父进程的页表复制给子进程,当子进程要对页面进行写操作时,才申请新的页面,然后将共享页面的内容复制到新申请的页面中去,并为新申请的页面填写三级页表中的内容。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。