背景

  • Read the fucking source code! --By 鲁迅
  • A picture is worth a thousand words. --By 高尔基

说明:

  1. Kernel版本:4.14
  2. ARM64处理器,Contex-A53,双核
  3. 使用工具:Source Insight 3.5, Visio

1. 概述

上篇文章分析到malloc/mmap函数中,内核实现只是在进程的地址空间建立好了vma区域,并没有实际的虚拟地址到物理地址的映射操作。这部分就是在Page Fault异常错误处理中实现的。

Linux内核中的Page Fault异常处理很复杂,涉及的细节也很多,malloc/mmap的物理内存映射只是它的一个子集功能,下图大概涵盖了出现Page Fault的情况:

下边就开始来啃啃硬骨头吧。

2. Arm64处理

Page Fault的异常处理,依赖于体系结构,因此有必要来介绍一下Arm64的处理。

代码主要参考:arch/arm64/kernel/entry.S

Arm64在取指令或者访问数据时,需要把虚拟地址转换成物理地址,这个过程需要进行几种检查,在不满足的情况下都能造成异常:

  1. 地址的合法性,比如以39有效位地址为例,内核地址的高25位为全1,用户进程地址的高25位为全0;
  2. 地址的权限检查,这里边的权限位都位于页表条目中;

从上图中可以看到,最后都会调到do_mem_abort函数,这个函数比较简单,直接看代码,位于arch/arm64/mm/fault.c

/*
* Dispatch a data abort to the relevant handler.
*/
asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
struct pt_regs *regs)
{
const struct fault_info *inf = esr_to_fault_info(esr);
struct siginfo info; if (!inf->fn(addr, esr, regs))
return; pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n",
inf->name, esr, addr); mem_abort_decode(esr); info.si_signo = inf->sig;
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
arm64_notify_die("", regs, &info, esr);
}

该函数中关键的处理:根据传进来的esr获取fault_info信息,从而去调用函数。struct fault_info用于错误状态下对应的处理方法,而内核中也定义了全局结构fault_info,存放了所有的情况。

主要的错误状态和处理函数对应如下:

static const struct fault_info fault_info[] = {
{ do_bad, SIGBUS, 0, "ttbr address size fault" },
{ do_bad, SIGBUS, 0, "level 1 address size fault" },
{ do_bad, SIGBUS, 0, "level 2 address size fault" },
{ do_bad, SIGBUS, 0, "level 3 address size fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 0 translation fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
{ do_bad, SIGBUS, 0, "unknown 8" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
{ do_bad, SIGBUS, 0, "unknown 12" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
...
};

从代码中可以看出:

  • 出现0/1/2/3级页表转换错误时,会调用do_translation_fault,实际中do_translation_fault最终也会调用到do_page_fault
  • 出现1/2/3级页表访问权限的时候,会调用do_page_fault
  • 其他的错误则调用do_bad,其中未列出来的部分还包括do_sea等操作函数;

do_translation_fault

do_page_fault

do_page_fault函数为页错误异常处理的核心函数,与体系结构相关,上图中的handle_mm_fault函数为通用函数,也就是不管哪种处理器结构,最终都会调用到该函数。

3. handle_mm_fault

handle_mm_fault用于处理用户空间的页错误异常:

  • 进程在用户模式下访问用户虚拟地址,触发页错误异常;
  • 进程在内核模式下访问用户虚拟地址,触发页错误异常;

    do_page_fault函数的流程图中也能看出来,当触发异常的虚拟地址属于某个vma,并且拥有触发页错误异常的权限时,会调用到handle_mm_fault函数,而handle_mm_fault函数的主要逻辑是通过__handle_mm_fault来实现的。

流程如下图:

3.1 do_fault

do_fault函数用于处理文件页异常,包括以下三种情况:

  1. 读文件页错误;
  2. 写私有文件页错误;
  3. 写共享文件页错误;

3.2 do_anonymous_page

匿名页的缺页异常处理调用本函数,在以下情况下会触发:

  1. malloc/mmap分配了进程地址空间区域,但是没有进行映射处理,在首次访问时触发;
  2. 用户栈不够的情况下,进行栈区的扩大处理;

3.3 do_swap_page

如果访问Swap页面出错(页面不在内存中),则从Swap cacheSwap文件中读取该页面。

由于在4.14内核版本中,do_swap_page调用的很多函数都是空函数,无法进一步的了解,大体的流程如下图:

3.4 do_wp_page

do_wp_page函数用于处理写时复制(copy on write),会在以下两种情况处理:

  1. 创建子进程时,父子进程会以只读方式共享私有的匿名页和文件页,当试图写的时候,触发页错误异常,从而复制物理页,并创建映射;
  2. 进程创建私有文件映射,读访问后触发异常,将文件页读入到page cache中,并以只读模式创建映射,之后发生写访问后,触发COW

关键的复制工作是由wp_page_copy完成的:

【原创】(十四)Linux内存管理之page fault处理的更多相关文章

  1. 【原创】(十)Linux内存管理 - zoned page frame allocator - 5

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  2. 【原创】(六)Linux内存管理 - zoned page frame allocator - 1

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  3. Linux内存管理 (11)page引用计数

    专题:Linux内存管理专题 关键词:struct page._count._mapcount.PG_locked/PG_referenced/PG_active/PG_dirty等. Linux的内 ...

  4. 【读书笔记】C#高级编程 第十四章 内存管理和指针

    (一)后台内存管理 1.值数据类型 Windows使用一个虚拟寻址系统,该系统把程序可用的内存地址映射到硬件内存中的实际地址,该任务由Windows在后台管理(32位每个进程可使用4GB虚拟内存,64 ...

  5. 【原创】(七)Linux内存管理 - zoned page frame allocator - 2

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  6. 【原创】(九)Linux内存管理 - zoned page frame allocator - 4

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  7. 【原创】(八)Linux内存管理 - zoned page frame allocator - 3

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  8. Linux内存描述之内存页面page–Linux内存管理(四)

    服务器体系与共享存储器架构 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...

  9. 伙伴系统之避免碎片--Linux内存管理(十六)

    1 前景提要 1.1 碎片化问题 分页与分段 页是信息的物理单位, 分页是为了实现非连续分配, 以便解决内存碎片问题, 或者说分页是由于系统管理的需要. 段是信息的逻辑单位,它含有一组意义相对完整的信 ...

随机推荐

  1. VirtualBox使用随笔

    1.virtualbox配置Android手机USB热点 host:Windows10;guest:windows XP/10 右击我的电脑 - 管理 - 设备管理器 - 网卡适配器,若手机正确vb连 ...

  2. Spring中配置DataSource数据源的几种选择

    从JNDI获得DataSource. 从第三方的连接池获得DataSource. 使用DriverManagerDataSource获得DataSource. 一.从JNDI获得DataSource ...

  3. 直击 KubeCon 现场 | 阿里云 Hands-on Workshop 亮点回顾

    相关文章链接[合集]规模化落地云原生,阿里云亮相 KubeCon China沉淀九年,一文看清阿里云原生大事件 2019 年 6 月 24 日至 26 日,KubeCon + CloudNativeC ...

  4. corn表达式——用于设置定时任务[转载]

    原文地址https://blog.csdn.net/xiaopihai86/article/details/50756306 http://www.cronmaker.com/  cron表达式验证网 ...

  5. HZOJ 通讯

    B. 通讯 题目描述 “这一切都是命运石之门的选择.” 试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短 信,并由此得知了伦太郎制作出了电话微波炉(仮). 为了掌握时间机器的技术, ...

  6. 2015年热门的国产开源软件TOP 50

    2015年热门的国产开源软件TOP 50 开源中国在 2015 年得到了快速的发展,单开源软件收藏量就接近 40000 款,其中不乏优质的国产开源项目.本文从软件的收藏.下载.访问等多角度挑选出了 2 ...

  7. AUTOSSH设置ssh隧道,实现反向代理访问内网主机

    内网主机上配置: autossh -M -CNR :localhost: ubuntu@123.207.121.121 可以实现将访问主机123.207.121.121的1234端口的数据,通过隧道转 ...

  8. [kuangbin带你飞]专题九 连通图E POJ 3177 Redundant Paths

    这个题最开始我想的是,直接缩点求双连通分量,连接这些双联通分量不就行了吗? 但是其实是不对的,双连通内部双联通,我们如果任意的连接一条边在这些双联通分量之间,他们之间有没有桥其实并不知道. 我应该是求 ...

  9. H3C IP的主要作用

  10. 解决某些手机RadioGroup中的RadioButton不居中(右移)问题

    最近一直在忙一个项目,页面的基本框架类似于QQ那样,有底部导航栏的,遂采用的是RadioButton来实现的.本来一直在我的模拟器上测试,页面展示是没啥问题的,效果图如下: 可是,坑爹的事今天却发生了 ...