LWN:对user-space pages进行明确的pin操作!-程序员宅基地

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

Explicit pinning of user-space pages

By Jonathan Corbet
December 13, 2019

原文来自:https://lwn.net/Articles/807108/

get_user_pages()和它所导致的kernel问题,已经在LWN上有过多篇介绍了,看这里:https://lwn.net/Kernel/Index/#Memory_management-get_user_pages 。简单来说,get_user_pages()是用来把user-space pages给钉在memory里面,供其他人(除了拥有它以外的其他人)来进行某种操作。这些操作可能会让kernel里其他一些以为对这个page有独占访问权限的部分碰到一些意外情况。John Hubbard提出了一组patch,虽然没有解决所有问题,但也是建立了一个解决这类问题的通用框架。

简要来说,get_user_pages()相关的问题有两种形式。一种是当kernel以为这个page里的内容不会改变的时候,某个外设却在这里进行了写入操作。另一种情况,如果这个memory是位于文件系统管理的persistent-memory设备上的情况,把page pin到memory的话,文件系统就不能对跟这个page有关的memory进行layout调整了。这个问题目前的解决办法是不允许在persistent-memory设备上进行这种非易失性page相关的pin操作,不过确实有些应用场景里面真的需要这样做,所以还是需要更好的解决方案。

这里部分问题来自get_user_pages()不会对pin到RAM的page进行任何专门记录。虽然会增长引用计数来确保不会被挤出memory,不过这样pin进内存的page跟其他那些途径pin进来的page完全无法区分。这样一来,我们虽然可以知道某个page是否有引用,却没有办法知道page是否是因为DMA I/O等目的pin进来的。

Hubbard的patch set就是针对这一点的。首先引入了一些新的内部函数来作为get_user_pages()系列函数的替代:

    long pin_user_pages(unsigned long start, unsigned long nr_pages,
		    	unsigned int gup_flags, struct page **pages,
		    	struct vm_area_struct **vmas);
    long pin_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
			       unsigned long start, unsigned long nr_pages,
			       unsigned int gup_flags, struct page **pages,
			       struct vm_area_struct **vmas, int *locked);
    int pin_user_pages_fast(unsigned long start, int nr_pages,
			    unsigned int gup_flags, struct page **pages);

在调用者看来,这些新的函数跟之前的get_user_pages()系列没有什么不同。所以切换起来很容易,只要替换一下调用的函数名即可。用这种方法pin进来的page在释放的时候必须要用新增的unpin_user_page()和unpin_user_pages()函数,这些是Hubbard在2019年上半年加进来替代put_user_page()的。

开发者该如何选择get_user_pages()和pin_user_pages()呢?在patch里增加的文档里面有描述。简单来说,如果pin page的目的仅仅是为了访问这些page里的内容,那么应该使用pin_user_pages()。如果是为了操作page structure而不是访问page内容本身,那么应给使用get_user_pages()。

新增的函数会告知kernel这次调用的目的,不过大家肯定还想知道如何记录管理这些pin进来的page。肯定需要某种引用计数,因为某个page可能会被pin多次,那么直到最后一个用户也调用unpin_user_pages()来释放后才会解除pin状态。理论上来说应该把引用计数放到struct page里面,不过有个小问题:这个struct里面的内容已经塞得很满了,又不能增大这个结构。

最终选择的方案是继续利用page现有的引用计数。调用get_user_pages()会导致引用计数加一从而完成pin的操作。而调用pin_user_pages()则会给它加GUP_PIN_COUNTING_BIAS,在这组patch的第23个patch里面定义为1024。Kernel代码可以通过调用page_dma_pinned()来确定某个page是否是这样pin进来的,其实只要简单检查page的引用计数是否超过了1024。

这样使用引用计数的话会有一些需要注意的地方。如果某个page通过正常方式增加引用计数而超过了1024的话,就会被误认为是pin进来做DMA的。patch set里也承认有这个行为,不过并不认为是一个问题,因为这样导致的误报并不会影响系统的行为。还有一个可能影响更大的问题,这个引用计数只有21个bit的空间,这意味着关于pin本身的引用计数就只有11个bit可用了。对多数情况来说应该够用了,不过如果是在pin一个compound page的时候,在每次pin一个tail page的时候都要把第一个page再pin一次。一个1GB的compound page包含256个4KB page,这样一来,这个page只要被pin 8次就会导致引用计数溢出了。

Hubbard认为解决方法是让get_user_pages()系列函数都要能认识huge page,如此一来引用计数就只需要增加一次就好了。不过这需要做不少改动,需要一些时间,因此没有包含在这组patch set里面,毕竟目前已经有了25个patch,改动已经很大了。

还有一点需要注意:kernel应该如何处理这样pin进来的page呢?也就是Hubbard所问的:“碰到这种情况之后该如何处理,留待后续patch吧”。比如说可以按Ira Weiny提出的layout lease方案,通过提供一个机制来让那些长期保持pin状态的page在有需要的时候可以unpin掉。目前还不清楚应该如何实现这个机制,可以说get_user_pages()的完整解决方案还需要不少时间。预计在2020 Linux Storage, Filesystem, and Memory-Management Summit峰会上会是一个热门议题。

至少kernel目前已经能够利用这个机制来识别并跟踪pinned page了,这是我们朝正确方向迈出的一小步。这些patch已经经过了多轮迭代,可能很快会合入Andrew Morton的-mm tree了。这样很可能会合入5.6 kernel中。

全文完

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

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

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Linux_Everything/article/details/103884537

智能推荐

基于UDP协议的实时影像传输程序_udp图像传输源码-程序员宅基地

文章浏览阅读600次,点赞3次,收藏4次。声明:本文仅作为个人创作成果过程备份,不具有专门的教育作用。程序还未完成,无法顺利运行是正常现象本人为非计算机相关专业大一学生,学习c语言仅为个人爱好,如有技术性错误请各位轻喷,欢迎大家提出任何具有建设意义的建议客户端(基于Linux平台):#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/socket._udp图像传输源码

HTML5使用ul li做下拉列表_html下拉列表用ul-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏8次。<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title></title> <style type="text/css"> *{ padding: 0px; margin: 0px; } a{ ..._html下拉列表用ul

ROS学习-记录和回放数据_rosbag record 指定topic-程序员宅基地

文章浏览阅读2.4k次,点赞2次,收藏11次。本博客将介绍怎么使用ROS系统来记录数据到一个.bag文件中,然后回放数据,在运行系统中产生类似的效果。记录数据(创建一个bag文件)从一个运行的ROS系统中记录topic数据,并存储到bag文件中。首先,打开一个Terminal窗口,运行roscore。roscore打开第二个Terminal窗口,运行turtlesim包中的turtlesim_node节点:rosrun turtlesim turtlesim_node打开第三个Terminal窗口,运行turtlesim包中的tu._rosbag record 指定topic

【Python&amp;GIS】Python实现批量导出面矢量要素(单个多面矢量->多个单面矢量)(1)-程序员宅基地

文章浏览阅读244次,点赞5次,收藏10次。之前发过很多文章都没有提到过环境配置,因为直接默认大家会使用Python了,今天这个博文加这个模块主要是因为我们使用的Python2.7!代码中有详细的注释。**变量就3个,第一个是arcpy的工作空间(没啥用),第二个就是想要拆分的矢量文件目录,第三个是输出矢量文件的文件夹。针对这个环境也不多说,你只要安装了ArcGIS就会有Python2.7,只要在Pycharm中将Python2.7的解释器加入到环境中即可。包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

大数据数据库之HBase:集群安装部署_hbase-env.sh-程序员宅基地

文章浏览阅读450次。文章目录前言1. HBase集群安装部署1.1 准备安装包1.2 修改HBase配置文件1.2.1 hbase-env.sh1.2.2 hbase-site.xml1.2.3 regionservers1.2.4 back-masters1.3 分发安装包1.4 创建软连接1.5 添加HBase环境变量1.6 HBase的启动与停止1.7 访问WEB页面1.8 停止HBase集群总结前言Hive的学习告一段落,接下来开始了解大数据主流NoSql数据库HBase,本文主要讲解HBase集群的安装部署,为_hbase-env.sh

视频汇聚平台视频智能分析一体机安防监控系统软件平台设备接入-程序员宅基地

文章浏览阅读358次,点赞10次,收藏5次。视频智能分析一体机在安防监控、智能交通、智慧城市等领域具有广泛的应用前景。它可以提高监控系统的智能化水平,减轻人工监控压力,提升监控效率和准确性,为各行业提供更安全、智能的监控解决方案。视频智能分析一体机作为一种先进的技术设备,在多个领域展现出了巨大的潜力和广泛的应用前景。特别是在安防监控、智能交通和智慧城市等领域,它已经成为了不可或缺的重要工具。4.弹出注册AIBox弹窗;5.输入前端设备ip地址;1.点击预注册AIBox;3.点击注册AIBox;6.输入设备用户名;6.输入盒子验证码;

随便推点

【组成原理-处理器】处理器的相关概念_平均指令周期计算公式-程序员宅基地

文章浏览阅读5.3k次,点赞22次,收藏137次。【组成原理-处理器】处理器的相关概念_平均指令周期计算公式

m基于BP神经网络的障碍物避障和路线规划matlab仿真_障碍物距离计算仿真-程序员宅基地

文章浏览阅读1k次。在BP神经网络中,隐含层数量对神经网络的性能有着至关重要的影响,如果隐含层数量过多,会大大增加BP神经网络的内部结构的复杂度,从而降低学习效率,增加训练时间;由于隐含层个数的设置没有明确的理论可以计算,通常情况下,采用逐次分析的方法获得,即通过对不同隐含层所对应的神经网络进行预测误差的仿真分析,选择误差最小情况下所对应的隐含层个数。BP神经网络的初始网络权值对网络训练的效率以及预测性能有着较大的影响,通常情况下,采用随机生成[-1,1]之间的随机数作为BP神经网络的初始权值。_障碍物距离计算仿真

微信小程序显示富文本内容图片溢出设置样式_小程序显示获取富文本图片样式-程序员宅基地

文章浏览阅读785次。微信小程序显示富文本内容,图片溢出问题_小程序显示获取富文本图片样式

react封装函数_封装React AntD的form表单组件-程序员宅基地

文章浏览阅读1.1k次。form表单在我们日常的开发过程中被使用到的概率还是很大的,比如包含了登录、注册、修改个人信息、新增修改业务数据等的公司内部管理系统。而在使用时这些表单的样式如高度、上下边距、边框、圆角、阴影、高亮等等都大同小异、大差不差且表单的功能基本相似,所以很有必要对这些表单来一个简单的封装。其实,封装组件的意义我们在上一篇封装react antd的表格table组件中已经介绍过了,这里不再做过多的描述了,..._react and from 表单库函数封装

PyTorch学习笔记(5)——论一个torch.Tensor是如何构建完成的?_aten/aten.h-程序员宅基地

文章浏览阅读6.4k次,点赞14次,收藏25次。最近在准备学习PyTorch源代码,在看到网上的一些博文和分析后,发现他们发的PyTorch的Tensor源码剖析基本上是0.4.0版本以前的。比如说:在0.4.0版本中,你是无法找到a = torch.FloatTensor()中FloatTensor的usage的,只能找到a = torch.FloatStorage()。这是因为在PyTorch中,将基本的底层THTensor.h TH..._aten/aten.h

前后端数据交互的几种方式_主流前后端交互方式有哪些-程序员宅基地

文章浏览阅读4.7k次,点赞4次,收藏21次。文章目录前言一、传统的ajax(原生ajax)二、jQuery中的ajax三、AngularJS(略)四、表单中数据的提交方式五、JSP中的JSTL标签库前言前后端数据交互的方式有哪些?常用的有哪些?一、传统的ajax(原生ajax)应首先创建 XMLHttpRequest对象这个对象包含的属性如下:1.readyState:对象的状态:0:未初始化1:open方法成功调用send方法未调用2:send方法已调用,尚未开始接收数据3:正在接收数据,但尚未接收完成4:完成.._主流前后端交互方式有哪些