Android 进程查杀机制 之ams lmkd kswapd
本篇针对android系统进程查杀机制做一个汇总和总结。主要涉及famework层ams通过adj进行进程查杀关键日志ActivityManager: Killingnative层lmkd通过内存阀值进行查杀关键日志lowmemorykiller: Killkernel层kswapd一、AMS查杀机制1、AMS查杀流程先附上AI生成的AMS查杀机制流程图┌─────────────────────────────────────────────────────────────────────────┐ │ 系统事件触发 │ │ (内存压力 / ANR / 强制停止 / 后台限制 / 应用清理) │ └──────────────────────────────┬────────────────────────────────────────────┘ ▼ ┌──────────────────────┐ │ 触发类型判断 │ └──────────┬───────────┘ ┌──────────────────────┼──────────────────────┐ ▼ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ updateOomAdj │ │ trimApplications│ │ ANR/ForceStop │ │ (OOM调整) │ │ (内存清理) │ │ (异常处理) │ └───────┬───────┘ └───────┬─────────┘ └───────┬───────┘ └────────────────────┴──────────────────────┘ ▼ ┌──────────────────────┐ │ OomAdjuster │ │ updateOomAdjLSP │ │ (计算OOM优先级) │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ 遍历LRU进程列表 │ │ (从低优先级到高优先级)│ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ 检查进程状态 │ └──────────┬───────────┘ ┌──────────────────────┼──────────────────────┐ ▼ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ CACHED进程 │ │ CACHED_EMPTY │ │ Isolated进程 │ │ (缓存进程) │ │ (空进程) │ │ (隔离进程) │ └───────┬───────┘ └───────┬─────────┘ └───────┬───────┘ ▼ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ 数量 限制? │ │ 数量 限制? │ │ 无服务运行? │ │ 或时间 阈值? │ │ 或时间 阈值? │ │ │ └───────┬───────┘ └───────┬─────────┘ └───────┬───────┘ │ 是 │ 是 │ 是 ▼ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ 生成kill reason│ │ 生成kill reason│ │ 生成kill reason│ │ cached #N │ │ empty #N │ │ isolated │ └───────┬───────┘ └───────┬─────────┘ └───────┬───────┘ └────────────────────┴──────────────────────┘ ▼ ┌──────────────────────┐ │ app.killLocked() │ │ (调用kill方法) │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ ProcessRecord │ │ killLocked() │ └──────────┬───────────┘ │ │ │ ▼ ┌──────────────────────┐ │ 检查是否已杀死 │ │ mKilledByAm │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ 打印日志 │ │ Killing app... │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ noteAppKill │ │ (记录kill信息) │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ ⭐ EventLog.writeEvent│ │ AM_KILL │ │ (打印am_kill日志) │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ Process.killProcess │ │ Quiet(mPid) │ │ (实际kill进程) │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ killProcessGroup │ │ (kill进程组) │ └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ 设置标志位 │ │ mKilled true │ │ mKilledByAm true │ └──────────┬───────────┘ ▼ [结束]1触发入口- OomAdjuster.java: updateOomAdjLSP()- ActivityManagerService.java: trimApplicationsLocked()- ProcessList.java: killAppIfBgRestrictedAndCachedIdleLocked()2决策逻辑- OomAdjuster.java: 遍历LRU列表根据进程状态决定是否kill- 检查条件进程数量、空闲时间、进程状态等3执行kill- ProcessRecord.java: killLocked()- 白名单检查isInLmkKillWhitelist() ⭐ 我们添加的- 打印日志EventLog.writeEvent(AM_KILL) ⭐ 这里打印am_kill日志- 实际killProcess.killProcessQuiet()4白名单检查位置- ProcessRecord.killLocked() 方法开始处- 在所有kill操作之前检查- 如果在白名单中直接返回不执行后续操作2、二、lowmemorykiller查杀机制lwkd进程属于native层启动的一个守护进程他的作用贯穿android世界的始终。他的另外一个大家都属于的名字lowmemorykiller。根据readme的介绍lmkd是用来对android系统内存检查的守护进程它通过终止不重要的进程来达到系统稳定运行的状态。在Linux Kernel 4.12之前是这项任务是放在了kernel进行管理在Linux Kernel 4.12之后移到了native层中因为在kernel进程管理中直接干掉某个应用进程太过暴力。后面介绍了我们可以通过一些属性的值来控制lmkd进程的效果如下ro.config.low_ram: choose between low-memory vs high-performance device. Default false.ro.lmk.use_minfree_levels: use free memory and file cache thresholds for making decisions when to kill. This mode works the same way kernel lowmemorykiller driver used to work. Default falsero.lmk.low: min oom_adj score for processes eligible to be killed at low vmpressure level. Default 1001 (disabled)ro.lmk.medium: min oom_adj score for processes eligible to be killed at medium vmpressure level. Default 800 (non-essential processes)ro.lmk.critical: min oom_adj score for processes eligible to be killed at critical vmpressure level. Default 0 (all processes)ro.lmk.critical_upgrade: enables upgrade to critical level. Default falsero.lmk.upgrade_pressure: max mem_pressure at which level will be upgraded because system is swapping too much. Default 100 (disabled)ro.lmk.downgrade_pressure: min mem_pressure at which vmpressure event will be ignored because enough free memory is still available. Default 100 (disabled)ro.lmk.kill_heaviest_task: kill heaviest eligible task (best decision) vs. any eligible task (fast decision). Default falsero.lmk.kill_timeout_ms: duration in ms after a kill when no additional kill will be done. Default 0 (disabled)ro.lmk.debug: enable lmkd debug logs, Default falsero.lmk.swap_free_low_percentage: level of free swap as a percentage of the total swap space used as a threshold to consider the system as swap space starved. Default for low-RAM devices 10, for high-end devices 20ro.lmk.thrashing_limit: number of workingset refaults as a percentage of the file-backed pagecache size used as a threshold to consider system thrashing its pagecache. Default for low-RAM devices 30, for high-end devices 100ro.lmk.thrashing_limit_decay: thrashing threshold decay expressed as a percentage of the original threshold used to lower the threshold when system does not recover even after a kill. Default for low-RAM devices 50, for high-end devices 10ro.lmk.psi_partial_stall_ms: partial PSI stall threshold in milliseconds for triggering low memory notification. Default for low-RAM devices 200, for high-end devices 70ro.lmk.psi_complete_stall_ms: complete PSI stall threshold in milliseconds for triggering critical memory notification. Default 700lmkd will set the following Android properties according to current system configurations:sys.lmk.minfree_levels: minfree:oom_adj_score pairs, delimited by commasys.lmk.reportkills: whether or not it supports reporting process kills to clients. Test app should check this property before testing low memory kill notification. Default will be unset.1、LMKD进程的启动1.1 三种启动方式同其他native进程一致他的启动还是通过init rc机制来启动。如下代码总结如下标记为core类的服务会在init.rc的on early-init或on init阶段被启动未显式设置disabled属性时core类服务会随init进程初始化自动启动。PS在core进行启动是为了防止核心服务没有启动导致系统异常监听sys.boot_completed开机属性然后传递--reinit参数进行完整启动。PS从后文可以了解到reinit会去读取一系列相关属性即这是完整启动最后监听属性变更传递--reinit参数应该是做成不需要重启系统就能够动态生效这些参数的效果1.2 主函数三部曲三、kswapd线程机制kernel_platform/msm-kernel/mm/page_alloc.c是 Linux 内核中负责物理页帧分配与管理的核心实现文件主要功能如下一、核心功能伙伴系统Buddy System实现alloc_pages()/free_pages()等接口通过2^n阶页块管理物理内存13处理内存碎片合并与拆分如__free_one_page()函数3页分配策略控制GFP标志GFP_KERNEL/GFP_ATOMIC等的分配行为14实现水位线WMARK_MIN/WMARK_LOW和内存回收触发逻辑3NUMA架构支持多节点内存分配__alloc_pages_nodemask()二、关键代码结构函数/宏功能说明__alloc_pages_nodemask分配页帧的核心逻辑含慢速路径/快速路径3get_page_from_freelist从空闲列表获取可用页帧3zone_watermark_ok检查内存水位是否满足分配需求3__free_pages_ok释放页帧到伙伴系统3三、与lmkd的关联当lmkd触发内存回收时最终会通过该文件中的分配器获取/释放物理页帧24。例如GFP_KERNEL分配可能触发直接内存回收__perform_reclaim低内存时通过__alloc_pages_slowpath进入回收流程3注该文件是内存管理子系统MM的核心组件代码路径通常为/mm/page_alloc.cMSM内核版本会包含高通平台的特定优化13。__setup_per_zone_wmarks这个函数是干什么的__setup_per_zone_wmarks是Linux内核中用于初始化内存管理区zone水位线watermark的关键函数其核心功能如下一、核心作用计算并设置三档水位值根据min_free_kbytes全局参数为每个zone动态计算WMARK_MIN最低警戒线、WMARK_LOWkswapd唤醒线、WMARK_HIGHkswapd休眠线14默认比例关系LOW MIN * 5/4HIGH MIN * 3/246NUMA架构适配针对不同内存节点node的zone独立计算水位考虑局部内存特性二、水位线的作用机制水位等级触发行为WMARK_HIGH内存充足kswapd线程进入休眠状态69WMARK_LOW空闲内存低于此值唤醒kswapd进行异步回收57WMARK_MIN触发直接内存回收direct reclaim可能阻塞进程分配请求三、典型调用流程系统启动时通过init_per_zone_wmark_min()调用该函数4根据公式计算每个zone的min_free_kbytes分摊值zoneminmin_free_kbytes×zonesizetotal_non_highmem_pageszonemintotal_non_highmem_pagesmin_free_kbytes×zonesize再基于此值推导其他水位四、相关代码逻辑// mm/page_alloc.c static void __setup_per_zone_wmarks(void) { // 计算各zone的min水位 for_each_zone(zone) { zone-watermark[WMARK_MIN] calc_min_watermark(zone); // 推导low/high水位 zone-watermark[WMARK_LOW] min_wmark_pages(zone) (tmp 2); zone-watermark[WMARK_HIGH] min_wmark_pages(zone) (tmp 1); } }该函数是内存分配器如get_page_from_freelist判断是否触发回收的核心依据
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2567736.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!