安卓内存机制

发布于:2024-05-07 ⋅ 阅读:(21) ⋅ 点赞:(0)


前言

安卓内存知识,不定期更新…

一、内存 LowMemoryKiller

Android的设计理念之一,便是应用程序退出,但进程还会继续存在系统以便再次启动时提高响应时间. 这样的设计会带来一个问题, 每个进程都有自己独立的内存地址空间,随着应用打开数量的增多,系统已使用的内存越来越大,就很有可能导致系统内存不足, 那么需要一个能管理所有进程,根据一定策略来释放进程的策略,这便有了lmk,全称为LowMemoryKiller(低内存杀手),lmkd来决定什么时间杀掉什么进程.

其实Linux有类似的内存管理策略——OOM killer,全称(Out Of Memory Killer), OOM的策略更多的是用于分配内存不足时触发,将得分最高的进程杀掉。而lmk则会每隔一段时间检查一次,当系统剩余可用内存较低时,便会触发杀进程的策略,根据不同的剩余内存档位来来选择杀不同优先级的进程,而不是等到OOM时再来杀进程,真正OOM时系统可能已经处于异常状态,系统更希望的是未雨绸缪,在内存很低时来杀掉一些优先级较低的进程来保障后续操作的顺利进行。

lowmemorykiller driver位于 drivers/staging/Android/lowmemorykiller.c

LMK驱动通过注册shrinker来实现的,shrinker是linux kernel标准的回收内存page的机制,由内核线程kswapd负责监控。

当内存不足时kswapd线程会遍历一张shrinker链表,并回调已注册的shrinker函数来回收内存page,kswapd还会周期性唤醒来执行内存操作。每个zone维护active_list和inactive_list链表,内核根据页面活动状态将page在这两个链表之间移动,最终通过shrink_slab和shrink_zone来回收内存页,有兴趣想进一步了解linux内存回收机制,可自行研究,这里再回到LowMemoryKiller的过程分析。

oom_adj:代表进程的优先级, 数值越大,优先级越低,越容易被杀.

当触发lmkd,则先杀oom_score_adj最大的进程, 当oom_adj相等时,则选择rss最大的进程.

/proc/< pid>/oom_adj
/proc/< pid>/oom_score_adj
/proc/< pid>/oom_score

参数设置:
1,6写入节点/sys/module/lowmemorykiller/parameters/adj
1024,8192写入节点/sys/module/lowmemorykiller/parameters/minfree
策略解读:
当系统可用内存低于8192个pages时,则会杀掉oom_score_adj>=6的进程
当系统可用内存低于1024个pages时,则会杀掉oom_score_adj>=1的进程

VSS虚拟耗用内存、(用处不大,包含共享库占用的内存,以及分配但未使用的内存,如malloc分配了但未写入,VSS很少用于判断一个进程内存的真实使用量)

RSS实际使用物理内存、(用处不大,包含共享库占用的内存,仅表示该进程使用的所有共享库的大小,而不管有多少个进程使用该共享库,故不能准确反映单进程的内存使用情况)

PSS实际使用的物理内存、(仅供参考,比例分配共享库占用的内存,按照进程数等比例划分)

USS进程独自占用的物理内存等分类。(非常有用,不包含共享库占用的内存)

二、常用的内存调优分析命令:

命令 描述
dumpsys meminfo 适用场景: 查看进程的oom adj,或者dalvik/native等区域内存情况,或者某个进程或apk的内存情况,功能非常强大;
procrank 功能: 获取所有进程的内存使用的排行榜,排行是以Pss的大小而排序。procrank命令比dumpsys meminfo命令,能输出更详细的VSS/RSS/PSS/USS内存指标。
cat /proc/meminfo 功能:能否查看更加详细的内存信息
free 主功能:查看可用内存,缺省单位KB。该命令比较简单、轻量,专注于查看剩余内存情况。数据来源于/proc/meminfo。
showmap 用于查看虚拟地址区域的内存情况 功能与cat /proc/[pid]/maps基本一致。
vmstat 主功能:不仅可以查看内存情况,还可以查看进程运行队列、系统切换、CPU时间占比等情况,另外该指令还是周期性地动态输出。