首页 > 其他分享 >rmap反向映射

rmap反向映射

时间:2023-01-01 23:13:30浏览次数:48  
标签:rmap struct 映射 vma anon 反向 address 进程 page

数据结构

AV & AVC & VMA

struct anon_vma { //AV是per VMA的
    struct anon_vma *root; //指向祖宗(root)进程的anon_vma
    struct anon_vma *parent; //指向父进程的anon_vma
    struct rw_semaphore rwsem; /* W: modification, R: walking the list */
    atomic_t refcount; //引用计数
    unsigned degree; //Count of child anon_vmas and VMAs which points to this anon_vma.
    struct rb_root rb_root;	/* Interval tree of private "related" vmas */
}
struct anon_vma_chain {
	struct vm_area_struct *vma;  //指向VMA
	struct anon_vma *anon_vma; //指向AV
	struct list_head same_vma; //把自己挂在VMA->anon_vma_chain链表上
	struct rb_node rb;			//把自己挂在anon_vma->rb_root红黑树上
	unsigned long rb_subtree_last;
};
struct vm_area_struct {
    struct list_head anon_vma_chain; //VMA和AVC是一对多,把AVC穿成链表
    struct anon_vma *anon_vma; //VMA和AV是一对一的关系
}

映射产生的过程

父进程产生匿名页面

用户态malloc分配虚拟内存->用户进程写内存->内核发生缺页异常->do_anonymous_page()

static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
		unsigned long address, pte_t *page_table, pmd_t *pmd,
		unsigned int flags)
{
    /* 保证vma有一个AV对应它,common case是已经有了,但没有的话就要分配并建立AVC VMA AV三者关系 */
    anon_vma_prepare(vma);
    /* 申请页面的动作 */
    page = alloc_zeroed_user_highpage_movable(vma, address);
    /* 设置该页面的匿名映射 */
    page_add_new_anon_rmap(page, vma, address);
}

准备VMA的AV和AVC

int anon_vma_prepare(struct vm_area_struct *vma) {
    struct anon_vma *anon_vma = vma->anon_vma;
	struct anon_vma_chain *avc;
    if (unlikely(!anon_vma)) {
        avc = anon_vma_chain_alloc(GFP_KERNEL);
        anon_vma = find_mergeable_anon_vma(vma);
        anon_vma = anon_vma_alloc();//如果find_mergeable_av失败
        vma->anon_vma = anon_vma; //建立三者关系
        anon_vma_chain_link(vma, avc, anon_vma);
        anon_vma->degree++; //Count of child anon_vmas and VMAs which points to this anon_vma.
    }
}
static void anon_vma_chain_link(struct vm_area_struct *vma,
				struct anon_vma_chain *avc,
				struct anon_vma *anon_vma)
{
	avc->vma = vma;
	avc->anon_vma = anon_vma;
	list_add(&avc->same_vma, &vma->anon_vma_chain);
	anon_vma_interval_tree_insert(avc, &anon_vma->rb_root);
}

设置该页面的匿名映射

/**
 * page_add_new_anon_rmap - add pte mapping to a new anonymous page
 * @page:	the page to add the mapping to
 * @vma:	the vm area in which the mapping is added
 * @address:	the user virtual address mapped
 */
void page_add_new_anon_rmap(struct page *page,
	struct vm_area_struct *vma, unsigned long address)
{
    /* 设置这个页可以交换到磁盘 */
	SetPageSwapBacked(page);
    /* 省略…… */
    /* 设置这个页面为匿名映射 */
	__page_set_anon_rmap(page, vma, address, 1);
}
/**
 * @exclusive:	the page is exclusively owned by the current process
                page被当前进程独占
 */
static void __page_set_anon_rmap(struct page *page,
	struct vm_area_struct *vma, unsigned long address, int exclusive)
{
	struct anon_vma *anon_vma = vma->anon_vma;
    /* 如果已经是匿名页 *//* 不理解 */
	if (PageAnon(page))
		return;
	/*
	 * If the page isn't exclusively mapped into this vma,
	 * we must use the _oldest_ possible anon_vma for the
	 * page mapping!
	 *//* 不理解 */
	if (!exclusive)
		anon_vma = anon_vma->root;

    /* 重点 */
	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
	page->mapping = (struct address_space *) anon_vma;
    /* 计算address在vma中的第几个页面 */
	page->index = linear_page_index(vma, address);
}

父进程产生匿名页面时的状态
image
总结:父进程产生匿名页时的反向映射操作,首先申请了AV和AVC,构建VMA、AV、AVC三者的关系,然后申请一个页面,将AV的地址(利用最低位表示该page是一个anon_page)设置到page->mapping中,将address在VMA中的第几个页面的信息设置在page->index中。
此时因为父进程还没有子进程,或者说之前fork的时候该page还没有分配,就不必处理父子进程之间复杂的AVC指针问题。

父进程fork子进程

父进程在fork()创建子进程时,子进程会复制父进程的VMA数据结构内容,并且复制父进程的PTE内容到子进程的页表中,实现父子进程共享页表。多个不同子进程的虚拟页面会同时映射到同一个物理页面。
另外,多个不相干的进程的虚拟页面可以通过KSM机制映射到同一个物理页面中,暂不讨论该技术

标签:rmap,struct,映射,vma,anon,反向,address,进程,page
From: https://www.cnblogs.com/cchanghao/p/17019220.html

相关文章

  • 对象到对象映射-AutoMapper
    AutoMapper是一个对象-对象映射器,可以将一个对象映射到另一个对象。用来解决一个看似复杂的问题,这种类型的代码编写起来相当枯燥乏味,官网地址:​​http://automapper.org/​......
  • node.js编写反向代理转发https
    node.js编写反向代理转发httpsconstcrypto=require("crypto");constmd5=function(str){constmd5=crypto.createHash('md5');md5.update(str);......
  • 华为路由器映射内部服务器到公网
    网络描述:客户内部有一台OA服务器,及提供外部使用,又供内部使用。在AR路由器上配置NATServer配置。拓扑如下:关键配置:AR1配置aclnumber2000 rule5permit interface......
  • TypeScript-映射类型(Mapped Types)
    +-readonly/?类型中的属性可以有readonly或者是?修饰,分别影响可变性和可选性。如下:typeAccount={readonlyid:number;name:string;age?:number;......
  • springcloud 学习八、Zuul 路由网关、路由的基本配置、路由访问映射规则
    前言案例的都是循序渐进的。案例的顺序:微服务讲诉->父工程maven的module建立和rest风格的请求->eureka的学习、三大组件,服务注册与消费->eureka的集群操作->ribbon的负载均......
  • 0016 常见错误com.example.adminspringboot.mapper.UserMapper.update
    错误截图  在使用mybatis中容易出现解决方法:在配置文件中加上路径书写:mybatis:mapper-locations:classpath:mapper/*.xml#扫描所有mapper下的xml文件 ......
  • 正向代理与反向代理
    概要:正向代理与反向代理的简述和区别......简述:一、代理的概念:类似于一个中介,在A和B的连接中间使用C作为中介,C就是一个代理,用于A,B直接连接的中间处理或是资源分配。二......
  • 关于正向传播、反向传播、梯度爆炸、梯度消失的理解
    假设有这样一个神经网络,包含一个输入层I,一个隐藏层H,一个输出层O  其中,输入层包含两个神经元,分别为i1和i2;隐藏层有两个神经元,分别为h1和h2;输出层有两个神经元,分别为o1......
  • linux防火墙 与nginx端口映射
    如果linux机器开启了防火墙,那么外部无法直接访问机器内部的端口,一般用nginx配置端口映射,可以多个服务的端口映射成对外暴露的一个端口nginx配置的端口映射的位置一般是:/......
  • 数据结构 玩转数据结构 7-6 基于链表的映射实现
    0课程地址https://coding.imooc.com/lesson/207.html#mid=13708 1重点关注1.1使用链表实现映射Map详见3.1用链表实现映射Map  2......