whitelabel error page什么意思_page fault时发生了什么

de5bc2f4a1b4d870a017fa576f9785ae.png

在Linux中,进程和内核都是通过页表PTE访问一个物理页面的,如果无法访问到正确的地址,将产生page fault(缺页异常)。

45316c0f8b1ef103138b0a8787585d41.png

由于造成内核空间和用户空间的page fault的原因不尽相同,因此其处理流程也有所区别(以x86为例,代码位于"/arch/x86/x86-mm/fault.c")。

void __do_page_fault(...)
{
    if (unlikely(fault_in_kernel_space(address)))
        do_kern_addr_fault(regs, hw_error_code, address);
    else
        do_user_addr_fault(regs, hw_error_code, address);
    ...
}

内核页面由于使用频繁,通常不会被换出,所以这里是"unlikely"。

do_kern_addr_fault()
    --> vmalloc_fault()

对于用户空间,需要区分多种情况,page fault的处理显得更为复杂。

do_user_addr_fault()
    --> handle_mm_fault()
        --> handle_pte_fault()

首先,访问的内存地址必须是合法的,所谓「合法」,就是该地址一定是落在进程的某个VMA区间内。

struct vm_area_struct vma = find_vma(mm, address);

if (unlikely(!vma)) {
    bad_area(regs, hw_error_code, address);
    return;
}
if (likely(vma->vm_start <= address))
    goto good_area;

假设现在一个进程的地址空间分布如下,那么address B是合法的(good area),address A就是非法的(bad area)。

67eb07c03f4d8c2305848eea87f7551c.png

地址落在进程的地址空间内,但对地址的访问权限不对(比如试图写入一个readonly的区域),也是非法的。访问了非法的地址,或者非法地访问了地址,就不是page fault那么简单了,将进一步上升到segmentation fault。

如果地址合法,权限也正确,那么还得分两种情况来讨论。第一种情况是PTE不存在,这会出现在:

  • 对于anonymous page,用户空间使用malloc()进行内存申请时(对应底层的实现是mmap或者brk),内核并不会立刻为其分配物理内存,而只是为请求的进程的rbtree管理的vma信息中记录(添加或更改)诸如内存范围和标志之类的信息。

只有当内存被真正使用,触发page fault,才会真正分配物理页面和对应的页表项,即demand alloction,对应的函数实现是do_anonymous_page()。通过mmap映射建立的heap和stack等内存区域,在初始未使用时,也适用于这样的规则。

5603c4b4a3f2ddb6eee6e1a28914c883.png
  • 对于page cache, 在发生内存回收后,部分text(code)段的页面会被discard,部分data段的页面会被writeback,之后再次访问这些页面,也将出现page fault。此时,需要从外部存储介质中,将页面内容调回内存,即demand paging,对应的函数实现是do_fault()
vm_fault_t handle_pte_fault(struct vm_fault *vmf)
{
    if (!vmf->pte) {
        if (vma_is_anonymous(vmf->vma))
            return do_anonymous_page(vmf);
        else
            return do_fault(vmf);
    }
    ...
}

ec62f848e0bb2545c911483000983fea.png
图片来源于http://jake.dothome.co.kr/wp-content/uploads/2017/01/do_fault-1.png

第二种情况是PTE存在,但其中的"P(resent)"位为0,说明这是一个之前被swap out出去的anonymous page。现在PTE里存储的不是物理页面的编号PPN,而是外部swap area中slot的编号swp_entry_t,需要通过do_swap_page(),执行swap in操作将页面的内容拷贝回内存。

/* orig_pte是指发生page fault时的PTE */
if (!pte_present(vmf->orig_pte))
    return do_swap_page(vmf);

eb887a440031df1af93ec554a6b51025.png

发生page fault时,如果目标页面驻留在外部存储器,那么需要开销较大的I/O操作,这种page fault被称为"major"的。而如果目标页面就在内存中(比如swap cache),只是缺少一个对该页面的引用而已,这种page fault不需要重新分配内存页面,代价较小,因此被称为"minor"的。

还是那个图书馆借书的例子,前台相当于内存,书库相当于磁盘,从前台直接取走就是"minor page fault",比如书到期了你还没有看完,可以在前台办完还书手续后马上再借(前提是这本书没有被其他读者预约),付出的代价就是多一次借书手续而已。

而如果你还了两个月再去借这本书,书已经被管理员上架了,你就需要自己去书架上按照类别寻找这本书,花费的时间自然较多,这就是"major page fault"。

参考:

  • Understanding page faults and memory swap-in/outs
  • http://www.chudov.com/tmp/LinuxVM/html/understand/node35.html
  • http://jake.dothome.co.kr/mm-fault/

原创文章,转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值