autojs遍历当前页面所有控件_伙伴系统:页面分配器_weixin_39889788的博客-程序员秘密

技术标签: autojs遍历当前页面所有控件  系统页面升级系统中  

48ea981d42fe298368f5e6e452a52bab.png

概述:

本篇主要是对伙伴系统的页面分配器的实现进行一个梳理。在内核中伙伴系统算得上内存管理的一个基石了,毕竟页面的分配全权由它负责,即使是slab分配器也是在它的基础上进行实现的。页面分配器的函数在内核中有着各种各样的版本,不论是返回虚拟地址的还是返回struct page指针的,最终都会调用一个共同的接口:__alloc_pages_nodemask()

页面分配API:

以下是几个常见的页面分配函数,可以看到最终都会调用__alloc_pages_nodemask()

__alloc_pages_node  /*返回struct page的指针*/
    __alloc_pages
    	__alloc_pages_nodemask

alloc_pages         /*返回struct page的指针*/
    alloc_pages_current
    	__alloc_pages_nodemask
        
__get_free_pages    /*返回页面的虚拟地址*/
    __get_free_pages
    	alloc_pages
            alloc_pages_current
            	__alloc_pages_nodemask

核心梳理__alloc_pages_nodemask():

上面我们看到__alloc_pages_nodemask()即页面分配器的'心脏'了,接下来我们就梳理下这颗'心脏'中都具体做了哪些事情,主要有三步:

__alloc_pages_nodemask
  prepare alloc_context   //1.准备参数
  get_page_from_freelist  //2.快路径尝试分配内存 
  __alloc_pages_slowpath  //3.慢路径尝试分配内存

细节如下:

faa5d045a9657917b8acf2a5b5f5ee2e.png

由于分配过程很复杂,会涉及到大量的判断,以及numa node和zone的选择,所以会根据用户传参、进程配置(process flags)以及系统配置(mem policy或cgroup等)去整理一些参数,通过这些参数来控制后续内存分配和内存回收的行为。

1. 参数整理:

对__alloc_pages_nodemask()中的形参进行处理,整合出三个关键变量alloc_mask、alloc_flag以及struct alloc_context。(第一次整理后参数给fasthpath使用,若fastpath分配失败,进入slowpath前还会微调这些参数)

alloc_mask:存放处理后的gfp_mask。
  处理主要包括:
  1.过滤无效的mask;
  2.根据是否开启cpuset添加__GFP_HARDWALL;
  3.若请求发生在进程中,继承任务的GFP_FS/IO的行为。

alloc_flag:存放一些功能行为的mask。
  功能行为包括:
  1.cpuset是否开启;
  2.watermark的水位线用哪根。
  3.请求发生在进程中,继承任务的PF_MEMALLOC_xx的行为。

alloc_context:存放了关于从哪获取pageblock的参数。
  参数主要包括:zonelist、nodemask和preferred_zoneref

2. 快路径(fastpath)分配:

get_page_from_freelist      //从preferred zonelist中分page
  zone_watermark_fast/ok    //检测水位,具体是min low high由ALLOC_WMARK_xx决定
    node_reclaim            //wmark不ok,就根据回收模式判断是否进行回收
  rmqueue  		    //wmark很ok,分配page
    rmqueue_pcplist  	    //order为0时,从pcp中分配
    __rmqueue_smallest      //order大于0时,从free_area[]中分配

快路径总结:
(整体进入for循环,遍历尝试zonelist中的zone直至分配内存成功或失败,for循环中的处理如下)
1. 参数检查,若有不满足,直接continue跳过当前zone;
2. 检查水位zone_watermark_fast/ok。其中high low min水位线用哪根儿具体由alloc_flags中的ALLOC_WMARK_xx标志决定;
3. 若水位不ok,则根据回收模式zone_reclaim_mode的设置,判断是回收或是跳过当前zone,倘若最终没一个zone是ok的,则快路径失败,进入慢路径slowpath。
4. 若水位很ok,都符合了的话则rmqueue函数尝试分配页面,其中会区分order-0和非order-0的情况。

watermark的检测:

首先wmark_pages()会根据alloc_flags中设置的是min或low或high去算出该zone的watermark是多少;然后将该watermark传入zone_watermark_ok()判断该zone的free pages是否满足该水线。(检查过程会根据内存分配的紧急程度放宽watermark)

(详见章节: 内存回收(一):watermark与lowmem_reserve)。

核心函数rmqueue():

get_page_from_freelist()函数中做了一系列检查,都是为了最终能调用rmqueue()函数从zone中拿到合适order的内存。细看上面的框图,我们可以发现rmqeue()中根据order是否为0会分别调用rmqueue_pcplist()或__rmqueue_smallest(),原因如下:

  • order=0:

内核中将order-0的请求和大于order-0的请求在处理上做了区分。现在的处理器动不动就十几个核,而zone就那么几个,当多个核要同时访问同一个zone的时候,不免要在zone的锁的竞争上耗费大量时间。社区开发者发现系统中对order-0的请求在内核中出现的频次极高,且order-0所占内存仅一个页的大小,于是就实现了per cpu的"内存池",用来满足order-0页面的分配,这样就在一定程度上缓解了伙伴系统在zone的锁上面的竞争。

static struct page *rmqueue_pcplist(...)
{
        /*关闭本地中断并保存中断状态(因为中断上下文也可以分配内存)*/
        local_irq_save(flags);
        /*获取当前CPU上目标zone中的per_cpu_pages指针*/
        pcp = &this_cpu_ptr(zone->pageset)->pcp;
        /*获取per_cpu_pages中制定迁移类型的页面list*/
        list = &pcp->lists[migratetype];
        /*从链表上摘取目标页面*/
        page = __rmqueue_pcplist(zone,  migratetype, alloc_flags, pcp, list);
        /*若分配成功,更新当前zone的统计信息*/
        if (page) {
                __count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
                zone_statistics(preferred_zone, zone);
        }
        /*恢复中断*/
        local_irq_restore(flags);
        return page;
}
  • order>0:

在__rmqueue_smallest()中从小到大循环遍历各个order的free_list链表,直到使用get_page_from_free_area()成功从链表上摘取到最小且合适(order和migratetype都合适)的pageblock

__rmqueue_smallest()
  get_page_from_free_area()

3. 慢路径(slowpath)分配

__alloc_pages_slowpath
    wake_all_kswapds	          //首先唤醒所有kswapd线程,并确保slowpath过程中一直是醒着的
    get_page_from_freelist        //调整一下alloc_flags,尝试分配
    get_page_from_freelist        //调整一下alloc_flags和zonelist,再试下分配
    __alloc_pages_direct_reclaim  //reclaim后再尝试分配,属于同步回收
    __alloc_pages_direct_compact  //compact后再尝试分配,属于同步回收
    __alloc_pages_may_oom         //反复尝试reclaim和compact后仍不成功,则oom杀进程后再尝试分配,属于同步回收

慢路径总结:

快路径(fastpath)检查了各个zone的low watermark,若所有zone的内存水位线都低于low,则失败并进入慢路径(slowpath)。

1. 慢路径第一件事就是先唤醒所有的kswapd内核线程展开异步回收。(异步回收)
2. 由于在进入慢路径时会对alloc_flags进行调整,且已经开启了异步回收,再次尝试分配或许会成功。
3. 再次调整alloc_flags以及zonelist后尝试分配或许会成功。
4. 调用__alloc_pages_direct_reclaim(),其中会先进行直接内存回收,然后尝试分配内存。(同步回收)
5. 调用__alloc_pages_direct_compact(),其中会进行内存压缩(或内存规整),扫描free_area[]对碎片化的内存进行整理,然后尝试分配内存。(同步回收)
6. 调用__alloc_pages_may_oom()触发OOM,杀掉得分最高的进程,然后尝试分配内存。(同步回收)
7. 整个过程会根据实际情况可能循环尝试3、4、5三个步骤,或循环尝试3、4、5、6四个步骤。

4. slowpath中的各种回收机制

下面梳理了slowpath中四种回收机制的调用关系,细节待补充。

4.1 slowpath中的kswapd(异步回收)

创建kswapd: kernel启动时会调用kswapd_init()为每个NUMA node都创建一个kswapd内核线程。

kswapd_init
  kswapd_run
    kthread_run(kswapd, ..)

唤醒kswapd: __alloc_pages_nodemask()分配过程中,当watermark低于low时会唤醒kswapd进行异步回收。

wake_all_kswapds
  wakeup_kswapd

4.2 slowpath中的reclaim(同步回收)

__alloc_pages_direct_reclaim
  __perform_reclaim
    try_to_free_pages
      do_try_to_free_pages
        shrink_zones
  get_page_from_freelist

4.3 slowpath中的compact(同步回收)

__alloc_pages_direct_reclaim
  __perform_reclaim
    try_to_free_pages
      do_try_to_free_pages
        shrink_zones
  get_page_from_freelist

4.4 slowpath中的OOM(同步回收)

__alloc_pages_may_oom
  out_of_memory
    oom_kill_process

原创文章,转载和引用请注明出处。

作者:Yann Xu

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

智能推荐

ffmpeg android 编译选项,FFmpeg学习—android 编译 ffmpeg 集成fdk-aac、x264 精简解码库..._哇塞5G的博客-程序员资料

#!/bin/bashNDK="/home/wh/android-ndk-r12b"SYSROOT=$NDK/platforms/android-9/arch-arm/TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64function build_one{./configure --prefix=$PR...

苹果7防水吗_苹果手机到底防不防水?_weixin_39895181的博客-程序员资料

苹果手机到底防不防水问题,分享一下自己的看法吧:迄今为止,没有一款 iPhone是真正意义的防水。苹果7代以前的机器不用说,没有任何的防水性能。7代以后屏幕四圈增加了密封胶,卡槽,按键设计了防水胶垫,但这些只能说密封性大大提高,只能防止生活水溅,小的雨水,手汗之类的,而不是能完全抵抗水龙头直接冲洗或者整个浸泡到水里那种。手机内部元器件精密复杂,进水受潮会有很大影晌,后期出问题的概率非常大,有的用户...

win10上编译flink1.10.0以运行在cdh6.3.0环境中_benpaodexiaowoniu的博客-程序员资料

在https://github.com/apache/flink/releases处点击下载flink-release-1.10.0.tar包,在win10的apache-maven-3.5.4中配置阿里源虽然阿里源https://maven.aliyun.com/mvn/view可以看到网友普遍使用的下面的库: &lt;mirror&gt; &lt;id&gt;alim...

电子计算机专业vs土木工程专业,2021工科就业前景好的专业排名_weixin_39917291的博客-程序员资料

2021工科就业前景好的专业排名2021-01-19 16:45:21文/陈宇航本文中,小编整理了工科就业前景好的专业排名,快来看看吧!工科就业前景好的专业排名1.土木工程专门培养掌握各类土木工程学科的基本理论和基本知识,能在房屋建筑、地下建筑、道路、隧道、桥梁建筑、港口及近海结构与设施工作的人员。2.机械设计制造及其自动能在机械工程领域从事机械产品研发、设计、制造、项目管理等工作的复合型工程技术...

BZOJ 4540: [Hnoi2016]序列 莫队算法_NOIAu的博客-程序员资料

Time Limit: 20 Sec Memory Limit: 512 MB Submit: 1412 Solved: 663Description给定长度为n的序列:a1,a2,…,an,记为a[1:n]。类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar。若1≤l≤s≤t≤r≤n,则称a[s:t]是a[l:r]的子序列。现在有q个询问,每个询问给定两个数l

android 支持user版本,user版本如何打开root权限之android8.1_Damong.Liu的博客-程序员资料

1.修改ro.adb.secure和ro.secure属性/code/1-android8.1/build/core$ git diffdiff --git a/core/main.mk b/core/main.mkindex 44ad271..947d7a3 100644--- a/core/main.mk+++ b/core/[email protected]@ -239,11 +239,11 @@ enabl...

随便推点

electron-vue项目 自动更新解决方案(附代码)_凉音、的博客-程序员资料

electron-vue的创建过程这里不再赘述。相信已经搜索到这篇文章的你,已经完成了这个过程,下面我们进入正题前言如果您的electron版本还是2.xx版本,需要更新electron版本,更新方式戳这里https://blog.csdn.net/weixin_43272648/article/details/104339699第一步,安装electron-updater依赖npminstallelectron-updater--save第二步,配置packa...

扒一扒国内做得比较优秀的无人机倾斜摄影公司_济南赛尔无人机的博客-程序员资料_倾斜摄影无人机

倾斜摄影技术在国内崛起说实话倾斜摄影虽然是作为一项国外引进的航空摄影技术,行业核心软件smart3D(CC)也是歪果仁出品,国内出的几款做实景三维的软件不客气的说大部分是处于又贵效果又不好的状态,毕竟软件开发是高投入高风险。言归正传,倾斜摄影技术的诞生促进了倾斜摄影硬件产品的发展,这一点,国内公司的产品研发和技术实力可以说不比国外的弱,如果能在国内找到适合的倾斜摄影产品和服务团队,就不必去...

vue-cli3 多页面 RangeError: Maximum call stack size exceeded_Ray_1234567的博客-程序员资料

昨天给项目配置vue多页面,结果一跑起来就报错: RangeError: Maximum call stack size exceeded - Array.join - loader.js:228 Function.Module._findPath internal/modules/cjs/loader.js:228:56 - loader.js:591 Funct...

【iOS-Cocos2d游戏开发之二十】精灵的基础知识点总汇(位图操作/贴图更换/重排z轴等)及制作简单遮盖层!..._weixin_33690963的博客-程序员资料

最近写了不少Cocos2d的博文了,那么由于Himi介绍的一般都是比较容易出错的问题或者比较受到关注的知识点,所以不少童鞋要求写个基础篇,那么这里Himi就举例最常用的精灵CCSprite来详细的介绍一些吧; 考虑到网上对于Cocos2d-iphone的中文教程已有很多,所以这里Himi会拿出一些教程没有提到的基础知识点来分享; 首先我们来创...

SpringBoot - 解决跨域请求问题_瞎胡扯的博客-程序员资料_allowedheaders

现在项目开发中,前后端分离越来越流行了,但在前后端分离通过 Ajax访问时会存在一个跨域的问题。即由于浏览器的安全性限制,不允许AJAX访问协议不同、域名不同、端口号不同的数据接口,否则会出报No 'Access-Control-Allow-Origin' header is present on the requested resource.错误。如下所示:强大的 Spring Boot支持通过设置CORS(跨源资源共享)来解决跨域请求问题。具体如下几种方式可以进行配置,我们选择一种...

bpmn-js起步_Zack_ZXY的博客-程序员资料_bpmn-js

通过本文逐步熟悉bpmn-js。 快速介绍:bpmn.js是一个BPMN2.0渲染工具包和web建模器。使用JavaScript编写,在不需要后端服务器支持的前提下向现代浏览器内嵌入BPMN2.0流程图。这使得它很容易的嵌入到任何web应用中。 这个库既可以是web查看器也可以是web建模器。使用查看器将BPMN2.0流程图嵌入到你的应用中并可以使用数据丰富你的流程图。使用建模...

推荐文章

热门文章

相关标签