- 论坛徽章:
- 2
|
本帖最后由 fireaway7 于 2014-05-11 16:34 编辑
第2章
2.4节需要理解的点:
*缺页异常产生的3个原因:线性地址与物理地址还没建立映射或已经撤消、物理页面已离开内存、访问权限不对
*asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code); // regs: 异常时的各种寄存器值,error_code:映射失败具体原因
a. 进入do_page_fault()的具体过程,学习“中断和异常”章节
b. 将引起缺页的地址写入CR2寄存器
c. if (in_context() || !mm),判断是否中断服务程序出错或mm还没建立,条件不满足时,表明超出了in_context()的检查范围
d. if (find_vma(mm, address))
找不到,表示要从用户空间访问系统空间,越界
找到了,且在找到区间的范围内,进一步查找原因,否则表示在空洞里,VM_GROWSDOWN可以确定空洞的位置在堆栈区还在在堆栈区下面还没分配出去的空间
e. find_vma()函数中,只对终点进行比较了,没对起点比较
f. 同一个mm可能被多个进程使用,如子进程,所以使用信号量
g. 越界的情况,需要通过crror_code进一步确定原因,“|-kernel/user-|-read/write-|-nopage/protection-|”,如果问题出在用户,向该进程发SEGSEGV信号
2.5节需要理解的点:
*%esp已经指向堆栈的最底部,此时如果需要调用函数,将返回地址压栈,就会出现越界情况,与2.4节过程大致相同,但最终会调用expand_stack()对堆栈进行扩展
*static inline int expand_stack(struct vm_area_struct *vma, unsigned long address); // vma:与address最近的区间,address:越界地址
a. 计算需要增加的页面个数
b. 判断资源限制
c. 扩张vma,并为新页面“安排”物理页面
d. handle_mm_fault(mm, vma, address, write);
a. pgd肯定存在(1个物理页面),pmd可能需要先分配(1个物理页面),但现层映射肯定等于pgd,pt可能需要先分配(1个物理页面),最终确定address对应的pte
b. static inline int handle_pte_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access, pte_t *pte);
a. do_no_page(mm, vma, address, write_access, pte);
a. do_anonymous_page(mm, vma, page_table, write_access, address); // 本情景缺的页跟文件映射、盘区交换都没关系,即vm_ops->nopage为空
a. page = alloc_page(); // 分配物理页面
b. mk_pte(page, vma->page_prot) // pte与page联系起来
e. 异常:重新执行“夭折”指令;中断、自陷:不再执行“夭折”指令
2.4节与2.5节对比,2.4节的空洞在堆栈区间之内,2.5节的空洞在堆栈区间下面,并且离堆栈底部小于32字节 |
|