0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

让我们一起来探索反向映射这个知识点

Linux阅码场 来源:Linuxer 作者:Linuxer 2020-09-18 10:31 次阅读

反向映射的目的是为了找到所有映射到某一个页面的页表项,从而可以对目标页做一些操作,比如切断映射。

反向映射一直是一个非常神奇的存在,今天我们就好好探索一下这个知识点。

创建

在反向匿名映射中除了page struct,一共有三个相关的数据结构:

vm_area_struct

anon_vma

anon_vma_chain

第一个数据结构我们已经见过了,是一个老朋友。而后两者就是为了构造反向匿名映射而新生的。我们先来看看这两个新的数据结构的样子。

anon_vma

anon_vma +----------------------------+ |root | = self |parent | = self | (struct anon_vma*) | |refcount | = 1 | (atomic_t) | |degree | = 1 | (unsigned) | +----------------------------+

这个结构由anon_vma_alloc()函数统一生成,上图中也显示了创造出来时候的样子。从这里看,也就是个带有上下级关系的这么一个结构。

anon_vma_chain

anon_vma_chain +----------------------------+ |vma | | (struct vm_area_struct*)| |anon_vma | | (struct anon_vma*) | | | |rb | | (struct rb_node) | |same_vma | | (struct list_head) | +----------------------------+

这个结构由anon_vma_chain_alloc()统一创建,貌似创建完了也不需要初始化,拿来后面就直接用了。

组合

到这里,大家应该感觉怪怪的,都不知道这些东西是个啥。别急,我把这些东西组合起来,可能你就会有一些感觉了。

在这里,我们把这三个重要的数据结构之间的组合关系展现给大家。当然这只是最简单的组合关系,目的是为了让大家能有一个感性的认识。

anon_vma_chain链接了anon_vma和vma

vma则会有指针指向自己的anon_vma

空口无凭,眼见为实。那为什么会长成这样的呢?接下来我们就来看看在内核中我们是如何将这些数据结构链接起来的。

链接

上一节的最后,我们看到了三个重要的数据结构通过链表和树连接在了一起,这一节我们就来看看他们是怎么连接起来的。

anon_vma_chain_link

往简单了讲,要连接这三个重要的数据结构,都靠一个函数:anon_vma_chain_link(vma, avc, 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); }

你对照这上面的图一看,和图上显示的一摸一样没有任何多余的步骤。

但是,关键的但是来了,如果你以为一切就这这么简单,那就too young too simple了啊。

接下来我们将从anon_vma_chain_link函数被调用的关系入手,去看看在实际运行中究竟会演化出什么样的变化来。

do_anonymous_page

首先出场的是函数do_anonymous_page,这个函数是在匿名页缺页中断时会调用的函数。

do_anonymous_page(vmf) __anon_vma_prepare(vma) avc = anon_vma_chain_alloc() anon_vma = find_mergeable_anon_vma(vma) anon_vma = anon_vma_alloc() vma->anon_vma = anon_vma anon_vma_chain_link(vma, avc, anon_vma)

从上面的流程可以看出,当发生缺页中断时,内核会给对应的vma构造anon_vma,并且利用avc去链接这两者。这种可以说是系统中最简单的例子,也是上图中显示的情况。

细心的人可能已经看到了,上面有一种情况是find_mergeable_anon_vma。如果这个函数返回一个可以重用的anon_vma,那么内核就可以利用原有的anon_vma了。此时这个图我们可以画成这样。

....................... ************************* . . * * av v avc v v vma v +-----------+ +-------------+ +-------------+ | |<------------|anon_vma vma|------------>| | | |<- | | | | +-----------+ +-------------+ +-------------+ ^ ^ ^ ^ . . * * . . ************************* . . . . . . ************************* . . * * . avc v v vma v . +-------------+ +-------------+ . ------|anon_vma vma|------------>| | . | | | | . +-------------+ +-------------+ . ^ ^ ^ . . * * ....................... *************************

其实此处我画得不够精确,av 和 avc之间应当是树的关系,而不是现在显示的链表的关系。但是我想意思已经表达清楚,即在一个进程中多个vma可以共享同一个anon_vma作为匿名映射的节点。

anon_vma_fork

看过了在单个进程中的情况,接下来我们来看看创建一个子进程时如何调整这个数据结构。这个过程由anon_vma_fork处理。

anon_vma_fork(vma, pvma) anon_vma_clone(vma, pvma) anon_vma = anon_vma_alloc() avc = anon_vma_chain_alloc() anon_vma->root = pvma->anon_vma->root anon_vma->parent = pvma->anon_vma vma->anon_vma = anon_vma anon_vma_chain_link(vma, avc, anon_vma)

这个函数很有意思,我还真是花了些时间去理解它。最开始有点看不清,所以我干脆退回到最简单的状态,也就是当前进程是根进程的时候。此时我才大致的了解了一点fork时究竟发生了什么。

话不多说,还是用一个图来表达

....................... ************************* . . * * av v avc v v vma v +-----------+ +-------------+ +-------------+ P | |<------------|anon_vma vma|------------>| | | |<----+ | | | | +-----------+ +-------------+ +-------------+ ^ ^ ^ ^ . . * * . . ************************* . . . . . . . . . . ************************* . . * * . avc v v * . +-------------+ * . |anon_vma vma| * . | | * . +-------------+ * . ^ ^ * . . * * ...................... * * * * * * * * ....................... * * . . * * av v avc v v vma v +-----------+ +-------------+ >+-------------+ C1 | |<------------|anon_vma vma|------------>| | | | | | | | +-----------+ +-------------+ +-------------+ ^ ^ ^ ^ . . * * ....................... *************************

P是父进程,C1是他的一个子进程。当发生fork时,page->mapping没有发生改变,所以依然需要能够从父进程的anon_vma上搜索到对应的页表。此时就得在父进程的rb_root树中保留一个子进程的avc。同时子进程又拥有自己的一套anon_vma。

可以说这个真的是非常有意思的。

对了,代码中还有一个函数anon_vma_clone,在这里我就不展开了。留给大家下来思考一下下。

使用

好了,到了这里我们已经拥有了一个非常强悍的武器 – 匿名反向映射。有了他我们就可以指哪打哪了。

内核也已经给我们准备好了扣动这个核武器的板机 – rmap_walk_anon。

rmap_walk_anon(page, rwc, true/false) anon_vma = page_anon_vma(page), get anon_vma from page->mapping pgoff_start = page_to_pgoff(page); return page_to_index(page) pgoff_end = pgoff_start + hpage_nr_pages(page) - 1; anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff_start, pgoff_end) rwc->rmap_one(page, vma, address, rwc->arg) -> do the real work

有了上面的基础知识,我想看这段代码就不难了。还记得上面看到过的那个rb_root么?对了,我们就是沿着这颗红黑树找到的vma,然后再找到了页表。

嗯,一切都感觉这么的完美。

原文标题:图解内存匿名反向映射reverse mapping

文章出处:【微信公众号:Linuxer】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • AV
    AV
    +关注

    关注

    2

    文章

    268

    浏览量

    44458
  • AVC
    AVC
    +关注

    关注

    0

    文章

    21

    浏览量

    10987
  • 映射
    +关注

    关注

    0

    文章

    44

    浏览量

    15784

原文标题:图解内存匿名反向映射reverse mapping

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    探索蓝牙5.4:让未来连接更近

    到底有哪些亮点和优势?它又将如何改变我们的生活呢?让我们一起来探索下。1、增强的广播功能蓝牙5.4引入了全新的广播功能,支持更高效的广播数
    的头像 发表于 09-10 16:58 811次阅读
    <b class='flag-5'>探索</b>蓝牙5.4:让未来连接更近<b class='flag-5'>一</b>步

    选2088还是3051?一起来说说TA们的不同~

    作为工业实践中最常用的现场仪表,变送器被广泛应用于各种工业自控环境,涉及水利水电、铁路交通、智能建筑、生产自控、航空航天、石化、油井、电力、船舶、机床、管道等众多行业。今天我们一起来看看「2088压力变送器」、「3051差压变送器」这两款变送器有啥区别?
    的头像 发表于 09-02 10:40 427次阅读
    选2088还是3051?<b class='flag-5'>一起来</b>说说TA们的不同~

    焊接机器人的崛起:未来工业自动化的领军者!

    随着科技的不断进步,焊接机器人已经成为了现代工业生产中不可或缺的部分。它们以其高效、精准的工作特性,极大地提升了生产效率和焊接质量。以下是关于焊接机器人的15个重要知识点让我们一起来
    的头像 发表于 06-13 10:33 474次阅读
    焊接机器人的崛起:未来工业自动化的领军者!

    模拟电子技术知识点问题总结概览

    给大家分享模拟电子技术知识点问题总结。
    的头像 发表于 05-08 15:16 1070次阅读
    模拟电子技术<b class='flag-5'>知识点</b>问题总结概览

    篇搞定DCS系统相关知识点

    目标。DCS系统广泛应用于各个行业,如化工、电力、制药等。在这些行业中,DCS系统可以实现对生产过程的集中监控和分散控制,提高生产效率和产品质量,降低能耗和减少环境污染,从而保证产品质量,并确保生产过程的安全可靠。 二.DCS系统知识点
    的头像 发表于 03-26 18:40 774次阅读
    <b class='flag-5'>一</b>篇搞定DCS系统相关<b class='flag-5'>知识点</b>

    #新开端、新起点,2024一起加油#

    ;2024一起加油\"则表达了大家共同努力,相互支持的决心和信念。 在2024年,无论你的目标是什么,都希望你能保持这种积极的心态,勇敢地面对挑战,不断地学习和进步。同时,也希望大家能够相互鼓励,共同前进,一起创造更美好的未来。 所以,
    发表于 02-26 21:01

    带您一起详细了解IEEE802.3bt(PoE++)的有关特点

    Hqst华强盛(盈盛电子)导读:带您一起详细了解IEEE802.3bt(PoE++)的有关特点,让我们对IEEE802.3bt(PoE++)协议有更具体的了解
    的头像 发表于 01-04 11:26 1897次阅读
    带您<b class='flag-5'>一起</b>详细了解IEEE802.3bt(PoE++)的有关特点

    浅谈初级电工必备知识点

    对于初学电工的朋友来说,掌握些基础且实用的知识点是非常重要的。本文旨在分享初级电工应该掌握的核心知识,帮助新手电工更好地入门和提升技能。
    的头像 发表于 12-26 10:44 994次阅读

    TCP协议面试常问知识点总结

    TCP 作为传输层的协议,是个IT工程师素养的体现,也是面试中经常被问到的知识点。在此,我将 TCP 核心的些问题梳理了下,希望能帮到各位。
    的头像 发表于 12-15 10:38 749次阅读
    TCP协议面试常问<b class='flag-5'>知识点</b>总结

    开关模式下的电源电流如何检测?这12个电路&amp;10个知识点讲明白了

    开关模式下的电源电流如何检测?这12个电路&10个知识点讲明白了
    的头像 发表于 12-06 16:04 740次阅读
    开关模式下的电源电流如何检测?这12个电路&amp;10个<b class='flag-5'>知识点</b>讲明白了

    c语言程序设计基础知识点

    程序设计的基础知识点。 首先,我们将从C语言的数据类型和变量开始。C语言提供了多种数据类型,包括整数、浮点数、字符和指针等。整数类型包括int、long和short等,浮点数类型包括float和double等,字符类型用于存储ASCII字符,指针类型用
    的头像 发表于 11-27 15:25 1560次阅读

    数字电位计知识点

    电子发烧友网站提供《数字电位计知识点.pdf》资料免费下载
    发表于 11-24 16:08 7次下载
    数字电位计<b class='flag-5'>知识点</b>

    三菱和西门子PLC输入接线知识点

    三菱和西门子PLC输入接线知识点
    的头像 发表于 11-21 10:01 691次阅读
    三菱和西门子PLC输入接线<b class='flag-5'>知识点</b>

    OFDM技术知识点

    电子发烧友网站提供《OFDM技术知识点.rar》资料免费下载
    发表于 11-18 14:25 1次下载
    OFDM技术<b class='flag-5'>知识点</b>

    下载汽车电力系统设计“秘籍”领好礼,一起来为“小新”解惑吧

    ,貌似在答疑之余,他还带来了套新的“ 干货秘籍 ”,一起来看看吧。 ps:文末有秘籍下载,同时还有好礼相送,记得滑到最后哦~ 森博森博,都说主驱逆变器是电动汽车的“心脏”,那这么重要的“心脏”器件在设计时应重点考虑哪些因素呢? 十分贴切的比喻
    的头像 发表于 11-16 19:10 333次阅读
    下载汽车电力系统设计“秘籍”领好礼,<b class='flag-5'>一起来</b>为“小新”解惑吧