相关源码文件: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方法中完成。

setOomAdj函数

参数amt正是我们要设定的adj以命令字(LMK_PROCPRIO)+ pid + uid + amt的协议格式向lmkd传输数据

从以上实现中能清楚的看到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_adjProcessList.remove方法与lmkd通信协议格式:[LMK_PROCREMOVE+pid] 移除进程

3.lmkd部分

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

3.1.lmkd守护进程

init启动脚本

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函数

init函数-1

init函数-2

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函数

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函数

mp_event_common函数-1

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

mp_event_common函数-2

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

3.5.find_and_kill_process函数

find_and_kill_process函数

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

3.6.mainLoop函数

mainLoop函数

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

3.7.ctrl_connect_handler函数

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函数

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级别的进程

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

  1. android 打开其它app,Android APP打开另一个APP的几种实现总结

    需求分析: 1.A点击拉起B: 2.如果B没安装,下载安装: 3.如果B已安转,未在后台运行点击打开B,传值账号密码,做跨登录: 4.如果B已安装,且正在后台运行,A打开B直接显示在后台运行的页面: ...

  2. 点击安装一个android app,Android APP打开另一个APP的几种实现总结

    需求分析: 1.A点击拉起B: 2.如果B没安装,下载安装: 3.如果B已安转,未在后台运行点击打开B,传值账号密码,做跨登录: 4.如果B已安装,且正在后台运行,A打开B直接显示在后台运行的页面: ...

  3. iOS 一个APP打开另一个APP

    环境:Xcode7.2.1,iOS Simulator 9.2, iPhone6s(9.3) 语言:Objective-C 和 Swift 通用 假定现在有两个APP:TestA和TestB,点击Te ...

  4. android点击另一个app,Android 怎么从一个APP中打开另外一个APP

    Android 如何从一个APP中打开另外一个APP 众所周知,在一个APP内部,从一个页面跳转到另外一个页面是使用startactivity函数来实现的. 同样的,对于应用之间的跳转也是如此的.应用 ...

  5. android 打开其它app,Android 在一个APP里打开另一个APP

    前言 不知道你们有没有注意过,每次打开一些软件的时候都会有广告引导页,有时候手滑点到了,会有进入手机上的另一个APP,这有没有引起你的注意呢? 运行效果图 正文 为了测试这个功能,首先要创建两个项目, ...

  6. Android 在app里面打开另一个app,加<uses-permission android:name=“android.permission.QUERY_ALL_PACKAGES“

    Android 在app里面打开另一个app 一.方式1:打开外部app,在新窗口打开. //打开外部app,新窗口打开private void doStartApplicationWithPacka ...

  7. Android在app中打开另一个app

    打开另一个app 知道包名和MainActivity类名之后 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(In ...

  8. Android Studio 打开Profiler后App闪退

    Android Studio 打开Profiler后App闪退 环境 Android Studio 4.1.1 Android 10 错误信息: 2020-12-24 16:06:21.870 300 ...

  9. iOS App 唤醒另一个App

    iOS App 唤醒另一个App 网上也有讲这块的,感觉讲得都不是很好.而且有一些细节根本没有讲清楚.这里重写整理一下相关知识点. 主要内容 URL Scheme 是什么? 项目中关键的配置 注意事项 ...

最新文章

  1. java基础之抽象类和接口
  2. VTK:图片之ImageShiftScale
  3. shell之case和循环语句(case语句的格式与举例)(for循环,while循环until循环语句的详解和continue,break解释, 九九乘法口诀表 ,等腰三角形)
  4. 【CodeForces - 864C】Bus (模拟,有坑)
  5. 携程赴港二次上市在即 “旅游营销枢纽”战略助价值重估
  6. SourceInsight初学使用笔记
  7. 莱斯康混响插件合集 – Lexicon Plugin Bundle macOS
  8. php中医处方系统简介
  9. Python文本处理之按行处理大文件
  10. vue-cropper 截图
  11. Win7 远程桌面限制IP
  12. 最通俗易懂的理解什么是数据库
  13. Java学习笔记 (码龄七年第一次写笔记 续2)
  14. 蚂蚁代理免费代理ip爬取(端口图片显示+token检查)
  15. int、tinyint、bigint的区别/MySQL中
  16. Pytorch深度学习基础 实战天气图片识别(基于ResNet50预训练模型,超详细)
  17. 11. Nginx HTTPS
  18. 如何用Github钩子做自动部署
  19. HTML基础知识(四)——浮动
  20. springboot毕设项目儿童早教课程管理系统5nv41(java+VUE+Mybatis+Maven+Mysql)

热门文章

  1. 暑假攻略:怎样让孩子过一个充实又省钱的假期
  2. Tensorflow学习笔记---1--Python基本操作
  3. iOS 使点击事件穿透透明的UIView
  4. mysql示例数据库
  5. java计算奇数阶魔方阵
  6. hdu 5326(基础题) work
  7. python 线程, GIL 和 ctypes
  8. [React] 尚硅谷 -- 学习笔记(四)
  9. HTML5新增-页面结构状态-列表-表单-音视频-全局兼容
  10. Modularity(模块化-CommonJS规范)