背景

  • 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. 概述

RMAP反向映射是一种物理地址反向映射虚拟地址的方法。

  • 映射

    页表用于虚拟地址到物理地址映射,其中的PTE页表项记录了映射关系,同时struct page结构体中的mapcount字段保存了有多少PTE页表项映射了该物理页。

  • 反向映射

    当某个物理地址要进行回收或迁移时,此时需要去找到有多少虚拟地址射在该物理地址,并断开映射处理。在没有反向映射的机制时,需要去遍历进程的页表,这个效率显然是很低下的。反向映射可以找到虚拟地址空间VMA,并仅从VMA使用的用户页表中取消映射,可以快速解决这个问题。

反向映射的典型应用场景:

  1. kswapd进行页面回收时,需要断开所有映射了该匿名页面的PTE表项;
  2. 页面迁移时,需要断开所有映射了该匿名页面的PTE表项;

2. 数据结构

反向映射有三个关键的结构体:

  1. struct vm_area_struct,简称VMA;

    VMA我们在之前的文章中介绍过,用于描述进程地址空间中的一段区域。与反向映射相关的字段如下:
struct vm_area_struct {
...
/*
* A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
* list, after a COW of one of the file pages. A MAP_SHARED vma
* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
* or brk vma (with NULL file) can only be in an anon_vma list.
*/
struct list_head anon_vma_chain; /* Serialized by mmap_sem &
* page_table_lock */
struct anon_vma *anon_vma; /* Serialized by page_table_lock */
...
}
  1. struct anon_vma,简称AV;

    AV结构用于管理匿名类型VMAs,当有匿名页需要unmap处理时,可以先找到AV,然后再通过AV进行查找处理。结构如下:
/*
* The anon_vma heads a list of private "related" vmas, to scan if
* an anonymous page pointing to this anon_vma needs to be unmapped:
* the vmas on the list will be related by forking, or by splitting.
*
* Since vmas come and go as they are split and merged (particularly
* in mprotect), the mapping field of an anonymous page cannot point
* directly to a vma: instead it points to an anon_vma, on whose list
* the related vmas can be easily linked or unlinked.
*
* After unlinking the last vma on the list, we must garbage collect
* the anon_vma object itself: we're guaranteed no page can be
* pointing to this anon_vma once its vma list is empty.
*/
struct anon_vma {
struct anon_vma *root; /* Root of this anon_vma tree */
struct rw_semaphore rwsem; /* W: modification, R: walking the list */
/*
* The refcount is taken on an anon_vma when there is no
* guarantee that the vma of page tables will exist for
* the duration of the operation. A caller that takes
* the reference is responsible for clearing up the
* anon_vma if they are the last user on release
*/
atomic_t refcount; /*
* Count of child anon_vmas and VMAs which points to this anon_vma.
*
* This counter is used for making decision about reusing anon_vma
* instead of forking new one. See comments in function anon_vma_clone.
*/
unsigned degree; struct anon_vma *parent; /* Parent of this anon_vma */ /*
* NOTE: the LSB of the rb_root.rb_node is set by
* mm_take_all_locks() _after_ taking the above lock. So the
* rb_root must only be read/written after taking the above lock
* to be sure to see a valid next pointer. The LSB bit itself
* is serialized by a system wide lock only visible to
* mm_take_all_locks() (mm_all_locks_mutex).
*/ /* Interval tree of private "related" vmas */
struct rb_root_cached rb_root;
};
  1. struct anon_vma_chain,简称AVC;

    AVC是连接VMAAV之间的桥梁。
/*
* The copy-on-write semantics of fork mean that an anon_vma
* can become associated with multiple processes. Furthermore,
* each child process will have its own anon_vma, where new
* pages for that process are instantiated.
*
* This structure allows us to find the anon_vmas associated
* with a VMA, or the VMAs associated with an anon_vma.
* The "same_vma" list contains the anon_vma_chains linking
* all the anon_vmas associated with this VMA.
* The "rb" field indexes on an interval tree the anon_vma_chains
* which link all the VMAs associated with this anon_vma.
*/
struct anon_vma_chain {
struct vm_area_struct *vma;
struct anon_vma *anon_vma;
struct list_head same_vma; /* locked by mmap_sem & page_table_lock */
struct rb_node rb; /* locked by anon_vma->rwsem */
unsigned long rb_subtree_last;
#ifdef CONFIG_DEBUG_VM_RB
unsigned long cached_vma_start, cached_vma_last;
#endif
};

来一张图就清晰明了了:

  • 通过same_vma链表节点,将anon_vma_chain添加到vma->anon_vma_chain链表中;
  • 通过rb红黑树节点,将anon_vma_chain添加到anon_vma->rb_root的红黑树中;

2. 流程分析

先看一下宏观的图:

  • 地址空间VMA可以通过页表完成虚拟地址到物理地址的映射;
  • 页框与page结构对应,page结构中的mapping字段指向anon_vma,从而可以通过RMAP机制去找到与之关联的VMA

2.1 anon_vma_prepare

之前在page fault的文章中,提到过anon_vma_prepare函数,这个函数完成的工作就是为进程地址空间中的VMA准备struct anon_vma结构。

调用例程及函数流程如下图所示:

至于VMA,AV,AVC三者之间的关联关系,在上文的图中已经有所描述。

当创建了与VMA关联的AV后,还有关键的一步需要做完,才能算是真正的把RMAP通路打通,那就是让pageAV关联起来。只有这样才能通过page找到AV,进而找到VMA,从而完成对应的PTE unmap操作。

2.2 子进程创建anon_vma

父进程通过fork()来创建子进程,子进程会复制整个父进程的地址空间及页表。子进程拷贝了父进程的VMA数据结构内容,而子进程创建相应的anon_vma结构,是通过anon_vma_fork()函数来实现的。

anon_vma_fork()效果图如下:

以实际fork()两次为例,发生COW之后,看看三个进程的链接关系,如下图:

2.3 TTU(try to unmap)Rmap Walk

如果有page被映射到多个虚拟地址,可以通过Rmap Walk机制来遍历所有的VMA,并最终调用回调函数来取消映射。

与之相关的结构体为struct rmap_walk_control,如下:

/*
* rmap_walk_control: To control rmap traversing for specific needs
*
* arg: passed to rmap_one() and invalid_vma()
* rmap_one: executed on each vma where page is mapped
* done: for checking traversing termination condition
* anon_lock: for getting anon_lock by optimized way rather than default
* invalid_vma: for skipping uninterested vma
*/
struct rmap_walk_control {
void *arg;
/*
* Return false if page table scanning in rmap_walk should be stopped.
* Otherwise, return true.
*/
bool (*rmap_one)(struct page *page, struct vm_area_struct *vma,
unsigned long addr, void *arg);
int (*done)(struct page *page);
struct anon_vma *(*anon_lock)(struct page *page);
bool (*invalid_vma)(struct vm_area_struct *vma, void *arg);
};

取消映射的入口为try_to_unmap,流程如下图所示:

基本的套路就是围绕着struct rmap_walk_control结构,初始化回调函数,以便在适当的时候能调用到。

关于取消映射try_to_unmap_one的详细细节就不进一步深入了,把握好大体框架即可。

【原创】(十五)Linux内存管理之RMAP的更多相关文章

  1. spark 源码分析之十五 -- Spark内存管理剖析

    本篇文章主要剖析Spark的内存管理体系. 在上篇文章 spark 源码分析之十四 -- broadcast 是如何实现的?中对存储相关的内容没有做过多的剖析,下面计划先剖析Spark的内存机制,进而 ...

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

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

  3. Linux学习之CentOS(二十六)--Linux磁盘管理:LVM逻辑卷的创建及使用

    在上一篇随笔里面 Linux学习之CentOS(二十五)--Linux磁盘管理:LVM逻辑卷基本概念及LVM的工作原理,详细的讲解了Linux的动态磁盘管理LVM逻辑卷的基本概念以及LVM的工作原理, ...

  4. 伙伴系统之伙伴系统概述--Linux内存管理(十五)

    在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Knowlton设计, ...

  5. Linux内存管理 (12)反向映射RMAP

    专题:Linux内存管理专题 关键词:RMAP.VMA.AV.AVC. 所谓反向映射是相对于从虚拟地址到物理地址的映射,反向映射是从物理页面到虚拟地址空间VMA的反向映射. RMAP能否实现的基础是通 ...

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

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

  7. Linux内存描述之高端内存–Linux内存管理(五)

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

  8. [转帖]五分钟彻底搞懂你一直没明白的Linux内存管理

    五分钟彻底搞懂你一直没明白的Linux内存管理 https://cloud.tencent.com/developer/article/1462476 现在的服务器大部分都是运行在Linux上面的,所 ...

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

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

随机推荐

  1. 2014年最热门的国人开发开源软件TOP100

    2014年最热门的国人开发开源软件TOP100 不知道从什么时候开始,很多一说起国产好像就非常愤慨,其实大可不必.做开源中国六年有余,这六年时间国内的开源蓬勃发展,从一开始的使用到贡献,到推出自己很多 ...

  2. 11 session 使用

    #session 使用app.secret_key = "dsada12212132dsad1232113"app.config['PERMANENT_SESSION_LIFETI ...

  3. 2019南昌网络赛-I. Yukino With Subinterval 线段树套树状数组,CDQ分治

    TMD...这题卡内存卡的真优秀... 所以以后还是别用主席树的写法...不然怎么死的都不知道... 树套树中,主席树方法开权值线段树...会造成空间的浪费...这道题内存卡的很紧... 由于树套树已 ...

  4. oracle连接多个扫描

    如果你对一个列和一组有限的值进行比较, 优化器可能执行多次扫描并对结果进行合并连接. 举例: SELECT * FROM LODGING WHERE MANAGER IN (‘BILL GATES’, ...

  5. C# 比较两张图片是否完全相同

    本文演示如何比较两张图片是否完全相同. (注意:如果是比较两张图片是否相似,则比较复杂,涉及到机器学习) 方法一:把图片保存到内存流中,然后转化成 Base64 字符串进行比较 using Syste ...

  6. javaObject类

    所有类的公共父类,一旦一个类没有显示地继承一个类则其直接父类一定是Object. 一切数据类型都可用Object接收 class OOXX  extends Object{}等价于class ooXX ...

  7. Cookie内不能直接存入中文,cookie转码以及解码

    如果在cookie中存入中文,极易出现问题. js在存入cookie时,利用escape() 函数可对字符串进行编码, 用unescape()进行解码 顺序是先把cookie用escape()函数编码 ...

  8. Python--day46--用户管理设计方案介绍

    1,基于用户权限管理: 2,基于角色的权限管理: 开始一个项目如果要100天的,可能70天都在设计,比如设计数据库表结构,最后30天才是写代码.设计是最难的,写代码是最简单的. 还有一个重要的一点,写 ...

  9. 陈志生:德国信贷工厂风控模式对P2P的启发

    上海合盘金融信息服务股份有限公司董事长陈志生 和讯银行消息 "2014中国金融论坛"于5月14-15日在北京召开,本次论坛主题为“全面深化金融体制改革与实体经济增长”.和讯网作为指 ...

  10. P1068 压缩技术

    题目描述 设某汉字由N × N的0和1的点阵图案组成. 我们依照以下规则生成压缩码.连续一组数值:从汉字点阵图案的第一行第一个符号开始计算,按书写顺序从左到右,由上至下.第一个数表示连续有几个0,第二 ...