autojs遍历当前页面所有控件_伙伴系统:页面分配器
概述:
本篇主要是对伙伴系统的页面分配器的实现进行一个梳理。在内核中伙伴系统算得上内存管理的一个基石了,毕竟页面的分配全权由它负责,即使是slab分配器也是在它的基础上进行实现的。页面分配器的函数在内核中有着各种各样的版本,不论是返回虚拟地址的还是返回struct page指针的,最终都会调用一个共同的接口:__alloc_pages_nodemask()
页面分配API:
以下是几个常见的页面分配函数,可以看到最终都会调用__alloc_pages_nodemask()
__alloc_pages_node /*返回struct page的指针*/__alloc_pages__alloc_pages_nodemaskalloc_pages /*返回struct page的指针*/alloc_pages_current__alloc_pages_nodemask__get_free_pages /*返回页面的虚拟地址*/__get_free_pagesalloc_pagesalloc_pages_current__alloc_pages_nodemask
核心梳理__alloc_pages_nodemask():
上面我们看到__alloc_pages_nodemask()即页面分配器的'心脏'了,接下来我们就梳理下这颗'心脏'中都具体做了哪些事情,主要有三步:
__alloc_pages_nodemaskprepare alloc_context //1.准备参数get_page_from_freelist //2.快路径尝试分配内存 __alloc_pages_slowpath //3.慢路径尝试分配内存
细节如下:
由于分配过程很复杂,会涉及到大量的判断,以及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中分pagezone_watermark_fast/ok //检测水位,具体是min low high由ALLOC_WMARK_xx决定node_reclaim //wmark不ok,就根据回收模式判断是否进行回收rmqueue //wmark很ok,分配pagermqueue_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_slowpathwake_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_initkswapd_runkthread_run(kswapd, ..)
唤醒kswapd: __alloc_pages_nodemask()分配过程中,当watermark低于low时会唤醒kswapd进行异步回收。
wake_all_kswapdswakeup_kswapd
4.2 slowpath中的reclaim(同步回收)
__alloc_pages_direct_reclaim__perform_reclaimtry_to_free_pagesdo_try_to_free_pagesshrink_zonesget_page_from_freelist
4.3 slowpath中的compact(同步回收)
__alloc_pages_direct_reclaim__perform_reclaimtry_to_free_pagesdo_try_to_free_pagesshrink_zonesget_page_from_freelist
4.4 slowpath中的OOM(同步回收)
__alloc_pages_may_oomout_of_memoryoom_kill_process
原创文章,转载和引用请注明出处。
作者:Yann Xu
autojs遍历当前页面所有控件_伙伴系统:页面分配器相关推荐
- autojs遍历当前页面所有控件_自定义控件(引入布局)
系统给我们提供了许多功能强大的控件,我们在需要时可以直接在布局中添加使用,但是有时候我们程序想要实现的功能往往因人而异,如:我们的程序需要在内个Activity的标题栏左侧有一个返回按钮(类似于iPh ...
- autojs遍历当前页面所有控件_纯前端表格控件SpreadJS V14.0发布:组件化编辑器+数据透视表 - 葡萄城开发工具...
SpreadJS 是一款基于 HTML5 的纯前端表格控件,兼容 450 种以上的 Excel 公式,具备"高性能.跨平台.与 Excel 高度兼容"的产品特性,可为用户提供高度类 ...
- autojs遍历当前页面所有控件_树形控件在生产力工具中的设计
惊!半年实践血泪史,3000 字深度好文,一个爱树的设计师手把手教你如何设计「树 」! 树形控件是种常见的设计模式,几乎与图形化用户界面同时诞生,通过结构化的组织方式逐级展示内容,让整体信息架构一目了 ...
- Xamarin自定义布局系列——PivotPage(多页面切换控件)
原文:Xamarin自定义布局系列--PivotPage(多页面切换控件) PivotPage ---- 多页面切换控件 PivotPage是一个多页面切换控件,类似安卓中的ViewPager和UWP ...
- 第三篇:属性_第二节:控件属性在页面及源码中的表示方式
一.属性在页面及源码中的表示方式 认真地看看页面中声明控件的代码,你会发现控件属性在页面中的表示千变万化.我们看看下面这些: <%@ Page Language="C#" A ...
- 怎么把一个控件放到tab页面上去?_移动端页面内容切换
# 移动端页面内容切换 上周做了一个和页面切换相关的需求,为了探寻在需求场景下最符合用户心理模型的交互方式,当时一共输出了有四五种方案.总结一下各种切换页面内容的方式的特点和他们适用的场景.## 一. ...
- 如何在用户控件中操作页面中的控件?
一般来讲我们会把功能集中在ASCX文件实现,以便能够多次使用,但在某种情况下,我们可能会用到对用户控件所在的页面容器进行操作. 其实如果想一下,道理也很简单,如果ASCX被使用了,其会出现在页面容器中 ...
- C# webbrowser控件点击页面按钮
用金山快盘时需要每天签到挣空间容量,一直都想写个定时程序实现,然后挂到实验室的服务器上.通过参考网上一些资料,自己动手实现一个利用webbrowser控件实现了自动点击网页按钮的功能,其实很简单的,下 ...
- 用户控件如何控制ASPX页面的控件
问题来自论坛http://topic.csdn.net/u/20120415/17/3f264265-b25c-4db8-a192-520e8a60e4c1.html?85396 问题分析,aspx页 ...
- 巧用Delegate在Silverlight多个页面、控件中传递回调方法
在论坛中看到经常有人碰到如何在SilverLight多个页面或者控件中传替参数或者值的问题,今天抽空通过Delegate机制实现回调实例方法重设动画参数的DEMO,分享给大家.最终结果如图: 在论坛中 ...
最新文章
- jersey rest webservice
- System memory 466092032 must be at least
- 020.day20 线程概述 多线程优缺点 线程的创建 线程常用方法 生命周期 多线程同步...
- IBM T61 键盘没有反映。
- 只需四步完成java JDK1.8的下载安装与配置【图文详解】
- 简单高效地控制高亮度LED
- 转:C++中STL用法总结
- 安装python缺少dll_解决win7操作系统Python3.7.1安装后启动提示缺少.dll文件问题
- java applet插件下载_Java Applet.zip
- 【CV2】Python中cv2使用小窗口显示高分辨率图片
- 10个妙招 在线视频下载方法大全
- 经纬度5位数和6位数差多少_经度和纬度的最大长度是多少?
- 数据评估:SD(标准差), 方差, 方差分析(ANOVA)
- linux虚拟内存设置为多少合适,虚拟内存怎么设置最好_虚拟内存设置多少合适
- oracle 定时 analyze,Oracle工具:Analyze
- IBM“移动优先”官网正式上线:苹果静候佳音
- 攻防世界(练习小题)
- 猿创征文|后端开发工程师提升开发效率神器推荐
- Springboot 2.0.x Redis缓存Key生成器,自定义生成器
- 高新技术企业避坑解读之“盲目跟风”
热门文章
- python --通过urlretrieve下载MP4文件
- 产品初探:银行理财产品简介
- 小学校本课程计算机前言,《创意手工》三河小学校本课程——序言
- 免费的查询IP归属地接口分享
- [导入]北京地区铁路客票代售点列表
- Java之批量分卷压缩与解压缩实现
- 迪拜政府和当地银行合作推出基于区块链的贷款平台
- mysql 1236错误_mysql故障~Got fatal error 1236 解决方法
- EPIC的服务器稳定吗,epic国内有服务器吗(epic服务器在哪)
- 菜哥学知识图谱(通过“基于医疗知识图谱的问答系统”)(三)(代码分析)