android app打开另一个app并触发按钮_Android进程调度:Low memory killer(4)修改版

相关源码文件:framework/base/service/core/java/com/android/server/am/ActiveServices.javaframework/base/service/core/java/com/android/server/am/ActiveManagerServices.java

1.adj更新时机

realStartActivityLocked: 启动ActivityresumeTopActivityInnerLocked: 恢复栈顶ActivityfinishCurrentActivityLocked: 结束当前ActivityfinishSubActivityLockedfinishVoiceTaskdestroyActivityLocked: 摧毁当前ActivityrealStartServiceLocked: 启动服务bindServiceLocked: 绑定服务(只更新当前app)unbindServiceLocked: 解绑服务 (只更新当前app)bringDownServiceLocked: 结束服务 (只更新当前app)sendServiceArgsLocked: 在bringup或cleanup服务过程调用 (只更新当前app)removeConnectionLockedserviceDoneExecutingLockedprocessNextBroadcast: 处理下一个广播processCurBroadcastLocked: 处理当前广播deliverToRegisteredReceiverLocked: 分发已注册的广播 (只更新当前app)removeContentProvider: 移除providerremoveContentProviderExternalUncheckedpublishContentProviders: 发布provider (只更新当前app)getContentProviderImpl: 获取provider (只更新当前app)setSystemProcess: 创建并设置系统进程addAppLocked: 创建persistent进程attachApplicationLocked: 进程创建后attach到system_server的过程;trimApplications: 清除没有使用appappDiedLocked: 进程死亡killAllBackgroundProcesses: 杀死所有后台进程.即(ADJ>900或removed=true的普通进程)killPackageProcessesLocked: 以包名的形式 杀掉相关进程;importanceTokenDiedsetProcessImportantupdateSleepIfNeededLockedsetHasTopUiupdateProcessForegroundLockedsetAppIdTempWhitelistStateLockedsetUidTempWhitelistStateLockedtrimApplicationssetHasOverlayUideliverToRegisteredReceiverLocked

相关文件:

framework/base/service/core/java/com/android/server/am/ProcessList.java

2.lmk的framework层部分

2.1.setOomAdj函数

Android进程调度:Low memory killer(3)中介绍到adj的设置最终在setOomAdj方法中完成。

37eb193ac1e9e950fa19a28cb7d12485.png

setOomAdj函数

参数amt正是我们要设定的adj以命令字(LMK_PROCPRIO)+ pid + uid + amt的协议格式向lmkd传输数据
426605dbaa91df8d86f47c38e8720d77.png
从以上实现中能清楚的看到lmkd是一个以SOCKET_SEQPACKET方式建立的TCP服务端,activityManager作为客户端的身份向其发起connect请求,请求成功后将数据推送给lmkd除了setOomAdj方法对应LMK_PROCPRIO命令与lmkd通信设定adj以外,在framework层还有两条命令分别用来与lmkd通信更新oom_adj和移除进程

2.2三大命令协议

[LMK_PROCPRIO]+ pid + uid + amt 设置ADJ [LMK_TARGET+minFree0+oom_adj0+minFree1+oom_adj1...] 更新oom_adj ProcessList.remove方法与lmkd通信协议格式:[LMK_PROCREMOVE+pid] 移除进程

3.lmkd部分

相关源文件:system/core/lmkd/lmkd.rcsystem/core/lmkd/lmkd.c

3.1.lmkd守护进程

6334fc4403b0459be34ae063bf902968.png

init启动脚本

cddc890b1bf7a8721a3d7cb26c030a49.png

main函数

ro.lmk.medium默认800,默认从oom_adj大于等于800的进程中选择出相应进程杀死以释放足够内存空间;ro.lmk.critical默认0,默认从oom_adj大于等于0的进程中选择出相应进程杀死以释放足够内存空间;ro.lmk.debug:调试使能开关,默认falsero.lmk.critical_upgrade:提升critical等级的使能开关,默认falsero.lmk.upgrade_pressure、ro.lmk.downgrade_pressure:提供一种更灵活的机制来判断内存紧张情况,查杀进程。 upgrade_pressure:前者表示当系统已用内存占比低于upgrade_pressure,说明交换出去太多的内存此刻系统内存紧张,如果可以的话请提升内存压力级别;后者表示当系统已用内存高于这个downgrade_pressure阈值,交换出去的内存较少说明系统含有足够的可用内存,可以适当降低杀内存压力级别,甚至不杀任何进程。(修改处)sched_setscheduler 将自己设置为实时进程,使用的调度器是 fifo。实时进程的优先级高于所有普通进程。对 fifo 调度器来说,在进程可运行(runnable)的时候,内核不会抢占它调用init初始化,init函数的实现细节参考3.2进入mainLoop,事件处理循环。实现细节参考3.6小节

3.2.init函数

a91d0dd4b7055fb3e1cdfe95b3ca57b7.png

init函数-1

f32b61f71da0e4bfe415a9443623f114.png

init函数-2

5ae77c74424d5e0b330c4f28665e90ac.png

init函数-3

创建epoll创建lmkd的文件描述符ctrl_lfd,(还记得否,客户端也有lmkd对应的fd)ctrl_lfd加入监听向epoll中添加一个读事件,事件data = ctrl_connect_handler,在监听到ctrl_lfd读事件时将被触发系统有两种lmk,一种是驱动层的lmk,另一种则是在应用层实现的lmkd。 如果INKERNEL_MINFREE_PATH不可访问,则使用的就是内核驱动的lmk。否则使用的就是应用层的。初始化mp事件,参考3.3小节

3.3.init_mp_common函数

be6aa016d16afd3df02ec1964b96da4e.png

init_mp_common函数

  • O_RDONLY | O_CLOEXEC方式打开/dev/memcg/memory.pressure_level返回mpfd
  • O_RDONLY | O_CLOEXEC方式打开/dev/memcg/cgroup.event_control返回evctlfd
  • 构建eventfd,这个东东是用来通信的,不同的进程可以通过这个FD来读写里面的数据从而达到通信的目的
  • “evctlfd mpfd levelStr”的格式字符串写到/dev/memcg/cgroup.event_control
  • evctlfd 加入epoll监听序列,事件data=event_handler,这个FD的读事件被监听到时将触发event_handler处理,也就是mp_event_common函数
  • eventfd存放在mpevfd数组中,“media” evfd对应index=0位置,“critical” evfd对应index=1位置
  • epoll会监听mpevfd数组中的两个fd,一旦有读事件发生就会触发事件相关的处理函数,实现细节参考3.4小节

3.4.mp_event_common函数

0fe1fdc46a375d5f09ef90e689b5d298.png

mp_event_common函数-1

147行:读取critical/media evfd对应的内容149行:读取用户已用内存占比和交换内存占比,如果读取失败则调用find_and_kill_process查杀进程,其实现参考3.5小节159~165行:.如果当前已用内存占比低于upgrade_pressure(40%),交换出去超过60%的内存说明系统内存很紧张,即将不足。如果当前内存压存压力级别低于critical,就将临界级别提升到critical;
c1984141c65beeecfa9f54efdb849183.png

mp_event_common函数-2

  • 169行:如果系统已用内存占比大于downgrade_pressure(60%),交换出去的内存低于40%说明系统可用内存还算充裕,不用通过杀死进程来获取更多内存;
  • 175行:系统的已用内存高于upgrade_pressure(40%)阈值,交换出去的内存低于60%说明内存压力有所缓解,此时如果内存压力级别是critical则可以将内存压力级别降为medium

3.5.find_and_kill_process函数

d68c39d7eaf8b68af79d1d122ee5aac8.png

find_and_kill_process函数

  • 如果is_critical为真,采用critical_oomadj(默认0);否则media(默认800)
  • find_and_kill_process函数从1000开始往下查找进程直到临界值,找到则杀掉该进程释放所占内存

3.6.mainLoop函数

c89072778b1774da54caf0a10a736f42.png

mainLoop函数

  • epoll_wait等待事件被触发,如果有监听事件触发,则执行对应data中的处理函数

3.7.ctrl_connect_handler函数

0c1bca2ce3db1f9faa44a47ad3cf3352.png

ctrl_connect_handler函数

accept接受客户端连接以新连接ctrl_dfd创建读事件,加入epollfd监听epoll事件的data = ctrl_data_handle,在该fd监听到读事件时将被触发,ctrl_data_handle实现细节参考3.8小节

3.8.ctrl_data_handler->ctrl_command_handler函数

5b83c281863e2c6ab20994bc9b8cd93e.png

ctrl_command_handler函数

解析协议第一个字节得到命令字,LMK_TARGET、LMK_PROCPRIO、LMK_PROCREMOVE分别对应不同的命令处理流程cmd_target函数更新/sys/module/lowmemorykiller/parameters/minfree和/sys/module/lowmemorykiller/parameters/adj文件中的内容cmd_procprio函数更新/proc/%d/oom_score_adj值cmd_procremove函数移除进程

3.9.minfree和adj文件

android:/# cat /sys/module/lowmemorykiller/parameters/minfree18400,23030,27608,32236,55286,82640 //单位:页android:/# cat /sys/module/lowmemorykiller/parameters/adj0,100,200,300,900,906

以上两条数据,可解释为如下含义:

当系统剩余内存低于82640页的时候,系统会杀死adj>=906级别的进程

当系统剩余内存低于55286页的时候,系统会杀死adj>=900级别的进程

当系统剩余内存低于32236页的时候,系统会杀死adj>=300级别的进程

当系统剩余内存低于27608页的时候,系统会杀死adj>=200级别的进程

当系统剩余内存低于23030页的时候,系统会杀死adj>=100级别的进程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值