关注了就能看到更多这么棒的文章哦~

Not-so-anonymous virtual memory areas

By Jonathan Corbet
September 3, 2021
DeepL assisted translation
https://lwn.net/Articles/867818/

计算机术语的名字有些时候是不那么直观的。但就算是业内的长期参与人员可能也会对 anonymous memory 这个名字也会觉得有些费解。Suren Baghdasaryan 发布了一组 patch set 正是希望让 anonymous memory 不那么匿名。目前看来,有一些开发者认为这个想法很有用,不仅可以帮助克服一上来的认知偏差,而且还又复活了一个 8 年前的 patch 从而将其纳入内核。

用户空间(user space)使用的内存分为两大类:有 file-backed(有对应文件的)和 anonymous(匿名的)。file-backed page 这些内存页都是与持久性存储中的一个文件中的 page 有着直接对应的关系。当该 page 尚未被污染时,其内容与磁盘上的内容完全相同。相应地,一个匿名页(anonymous page)与文件系统中的文件就没有关联了。这些 page 用来存放进程中的数据区、堆栈等。如果一个匿名页必须得要写入持久性存储了(通常是为了回收这个 page 来挪作其他用途),那就必须要在 swap 区域先分配好空间来存放其对应内容。

每个进程中是有对应文件的 memory page 更多呢,还是匿名页更多呢?这在不同的工作场景下是不一样的。很多情况下进程中大部分 page 都是匿名页。尤其是在大量的云计算客户端的工作场景中更加是这样,这些客户端程序往往不怎么使用本地文件。安卓设备就是一个典型的例子。如果有人试图针对这种工作场景的内存使用情况进行优化,那么匿名页就会给他们带来更多挑战。因为 page 是匿名的,也就是没有它们是如何被创建的这些信息,所以很难知道各个匿名页都被用来做什么了。

这一点还是可以改善的,那就是让匿名页面变得不那么匿名。如果能够知道是用户空间的哪个子系统或函数库创建的这个 page,就会更容易弄清楚谁是最主要的使用者。例如系统中如果记录了有多少匿名页是由 jemalloc 库创建的这个信息,就可以帮助确定对 jemalloc 的使用是不是一个我们应该优先优化的目标。然而,Linux 系统并不容易(甚至不可能)获得这类信息。

要想让情况变得更好,就需要从用户空间获得一些配合,因为内核不可能知道具体是用户空间的哪个子系统正在分配当前这个 page。这组 patch set 的核心就是 Colin Cross 的一个用来帮助完成这个工作的 patch,它最早在 2013 年就发布出来了,增加了一个新的 prctl() 操作。

prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, len, name);

这个函数会把 name 跟从 start 开始的 len 长度的匿名页关联起来。实际上这个 name 是跟用来描述这一段内存范围的虚拟内存区域(VMA)结构关联起来的。因此,实际上所有属于给定范围内的 VMA 的 page 内的分配都将得到这个 name,即使这些 page 本身不在这个范围内。每个 mmap() 调用通常会创建一个 VMA(尽管有一些情况会比较复杂),所以与任何指定 VMA 相关的所有 page 通常都是按同样的方式创建的。

每个进程的 /proc 目录下的 maps 和 smaps 文件中已经包含了很多关于该进程的 VMA 信息。在合入了这组 patch 之后,这些文件也将包含与 anonymous VMA 相关联的 name(如果之前 name 已经关联上来的话)。在接受这个 name 之前,会先检查这个 name 是否可以被 print 出来。系统工具就可以利用这些信息来将 page 与这些 name 关联起来,从而能跟创建这些 page 的子系统关联起来。

给 VMA 分配一个名字看起来并不困难,但事实上这是这个 patch 中最棘手的部分。一个系统中可以有很多进程,每个进程都可以有很多 VMA,所以这些 name 的管理方面需要能很容易地扩展。早期版本的 patch set 曾尝试直接指向用户空间所所提供的 name,这样就不需要在内核中分配内存了,但是,正如 Kees Cook 所指出的,它也带来了一些有意思的 security 问题。当时 Cook 建议直接将字符串复制到内核空间。

虽然复制字符串的做法是可行的,但仍有一个小问题:当一个进程进行 fork 时,它的 VMA 会被复制给新的子进程所用。那么现在所有这些 name 字符串也必须要被复制了。Baghdasaryan 做了一个最坏情况的测试,也就是用一个进程创建了 64000 个 VMA,给每个 VMA 分配了一个很长的 name,然后调用 fork(),结果是性能下降了近 40%。即使这种情况在现实世界的工作场景中应该不会出现,但这种下降幅度已经足以引起人们的关注了。

为了避免得到过得的抱怨,Baghdasaryan 增加了一个机制来实现 name 的公用机制,并且带有引用计数。这样一来现在 fork() 调用就只需要增加引用计数而已,不用再分配内存以及复制字符串了。采用了这个新增机制之后,最坏情况下,性能降幅 "减少到了原来降幅的 1/3 ~ 1/4",而且据说在那些合理的测试场景下都看不到有下降了。

这个功能显然是很有用的,安卓已经使用这个机制很多年了,它一直带着之前最早期的那个版本的 patch。到目前为止,review 反馈意见都集中在一些较小问题上——例如 name 中可以使用哪些字符。因此,看起来要合入这组 patch set 没有太多困难需要解决了。对于这个功能来说,八年的等待应该足够了,anonymous page 可能很快就会不再那么
anonymous 了。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

LWN:让vma的匿名页不再匿名!相关推荐

  1. Linux内存管理:反向映射机制(匿名页,文件页和ksm页)

    目录 1.反向映射的发展 2.反向映射应用场景 3.匿名页的反向映射 4.文件页的反向映射 5.ksm页的反向映射 6.总结 7.作者简介 8.推荐阅读 为了系统的安全性,Linux内核将各个用户进程 ...

  2. Linux 匿名页的反向映射

    我们知道LINUX的内存管理系统中有"反向映射"这一说,目的是为了快速去查找出一个特定的物理页在哪些进程中被映射到了什么地址,这样如果我们想把这一页换出(SWAP),或是迁移(Mi ...

  3. Linux内存 匿名页,学点linux之四:内存

    内存也是一大块 第二天·内存 分页机制 缓冲区溢出攻击,注意rw权限保护 用户态不能访问内存态,inter,amd的漏洞,meltdown,从用户空间偷取了内核空间数据,熔断漏洞 内存分zone DM ...

  4. linux匿名页 文件页,文件页和匿名页

    文件页和匿名页 文件页 内存回收, 也就是系统释放掉可以回收的内存, 比如缓存和缓冲区, 就属于可回收内存. 它们在内存管理中, 通常被叫做文件页 (File-backed Page). 大部分文件页 ...

  5. LWN:针对透明巨页的shrinker!

    关注了就能看到更多这么棒的文章哦- The transparent huge page shrinker By Jonathan Corbet September 8, 2022 DeepL assi ...

  6. 抛弃UITableView,让所有列表页不再难构建

    首先要对点进来的看官说声sorry,我标题党了.? 虽然抛弃UITableView是不存在的,但是看完这篇文章确实能让90%的列表页抛弃UITableView,让界面易实现易复用. 下面我将以第三人称 ...

  7. java中抽象类的匿名子类和匿名对象

    package com.atguigu.com;/** **抽象类的匿名子类和匿名对象*** * * */public class PeronTest {public static void main ...

  8. C语言 匿名联合体和匿名结构体

    C语言 匿名联合体和匿名结构体 匿名联合体和匿名结构体顾名思义,就是没有名字的联合体和结构体,没有名字哪怎么用?拿来用? 在嵌入式数据通信里面,大部分都是使用联合体,将有实际意义的结构体和字节数组互相 ...

  9. C#泛型委托,匿名方法,匿名类

    C#泛型委托,匿名方法,匿名类 class Test{delegate K proxy<T, K>(T t, K k); //泛型委托,注意返回值的写法,返回值的类型K先于其声明proxy ...

最新文章

  1. 一步步实施 DevOps (三)
  2. windows ping默认参数
  3. SpringBoot 后台管理系统
  4. Linux 命令之 tcpdump -- 监听网络流量
  5. uvm 形式验证_这究竟属于下一代验证的方法、语言还是工具?||路科验证
  6. java编写两邮件传输,JAVA邮件发送(文字+图片+附件)【源码】
  7. 判断一个数是偶数还是素数 做相应处理并排序输出
  8. 一个关于数组数据检查的问题,有没有更好的方法。
  9. php进程池不释放,php-fpm 进程池优化方法
  10. 提升谷歌chrome浏览器下载速度的方法
  11. 【014】求字体-上传图片自动识别字体
  12. 特殊字符ascii码
  13. IDEA关联MySQL数据库库
  14. Python:PIL库中getpixel()-方法的使用
  15. 电影网站 php asp,moviewebsite 这是一个电影网站的源码,基于asp技术实现.仅供交流学习 WEB(ASP,PHP,...) 238万源代码下载- www.pudn.com...
  16. 你们以为洗白了张柏芝,自己就不是婊子
  17. 数据传输 -- 字符串报文
  18. Linux文件权限:特殊权限、权限属性、权限掩码
  19. 重庆印象-大礼堂广场
  20. 软件项目质量管理策略

热门文章

  1. smartctl/hdparm对usb 硬盘识别的原因
  2. jquery.fileDownload.js
  3. 数据库之SQL基本数据类型
  4. shell编程100例
  5. pycharm 配置局域网访问,局域网无法访问解决办法
  6. 计算机组成原理为什么要学,学习计算机组成原理的感想
  7. android生成分享长图并且添加全图水印
  8. Android SDK环境配置
  9. Dubbo远程调用找不到服务异常
  10. python如何访问私有变量_Python基础_私有变量访问限制