1. 收集pagefault handler的相关信息,存入vmf结构体,并调用vma->vm_ops->fault进行缺页处理(完成页面的调入工作),返回的页存储在vmf.page中
2. 如果需要写访问,则需要区分私有映射和共享映射。
a. 如果是私有映射,首先调用anon_vma_prepare为vma区域建立一个新的anon_vma实例,并调用alloc_page_vma(页的分配过程是从伙伴系统进行分配的)分配一个新页page。最后调用copy_user_highpage函数将vmf.page所指向的页拷贝到新分配的页page中,创建数据副本。
b. 如果是共享页,首先进行一些安全检查,比如该页是否具有写权限等等,最后设置写标记page_mkwrite = 1
3. 通过1、2步操作,已经基本确定的页的位置,那么下一步工作就是将页与相应的进程建立联系,即将页加入到进行的页表,并合并到逆向映射数据结构中。
4. 为了确保新页的内容在用户空间可见,需要调用flush_icache_page更新缓存。
5. 调用mk_pte获取指向只读页(刚刚获取的那一页)的页表项,接着检查该页是否需要建立写权限(if (flags & FAULT_FLAG_WRITE)), 如果是,则调用maybe_mkwrite为该页显式设置写权限。
6. 检查该页是否是匿名页,如果是,则调用lru_cache_add_active将该页加入到LRU缓存的活动区域,接着调用page_add_new_anon_rmap将该页集成到逆向映射中。如果是基于文件映射的页,则调用page_add_file_rmap建立文件与页表项之间的逆向映射。
7. 调用update_mmu_cache更新处理器MMU缓存,因为页表已经修改。
阅读(3487) | 评论(0) | 转发(0) |