当前位置:首页 » 安卓系统 » android进程的优先级

android进程的优先级

发布时间: 2023-08-16 18:11:33

① Android 进程管理篇(四)-cpu限制

梳理Process进程相关知识点,再继续补充点内容。

linux系统中对进程的管理无非是从调度策略、优先级以及CPU限制三个角度进行配置与管理,那么Android中主要是通过AMS来管理应用程序进程的,是不是也是从这三个方面进行管理的呢?答案是肯定的,那么本篇文章先来看看cpuset负载均衡在AMS中是如何应用的。

cpuset是Linux cgroup子系统,它为cgroup任务分配单独的CPU和内存。单独分配CPU即表明进程可调度cpu范围。cpu按不同的芯片,大小核数目和频率都有差别,大核频率高处理速度相对比小核快,而Android系统实际上还是响应优先于吞吐的交互型系统,因此Android AMS对进程管理于不同优先级的进程在调度cpu限制上会做有一些策略,以保证更好的交互响应。

还是回到AMS中与adj相关的有三个方法,这三个方法值得看一万遍,每一遍都会有新收获:

聚焦到computeOomAdjLocked方法,该方法主要是根据进程的四大组件状态决定当前进程的adj优先级。

以TOP_APP为例,这里ProcessRecord 的curSchedGroup属性对应的是cup调度组,而在后续applyOomAdjLocked中会执行Process的setProcessGroup方法。

调用Process的setProcessGroup方法

setProcessGroup是个native方法,并且这里分了若干类型的group,这里看top app优先级是最高的。接着jni到native

这里直接调用sched_policy.cpp的set_cpuset_policy,并传入对应的pid和SchedPolicy

这里主要就是通过policy对应具体的fd句柄,然后通过add_tid_to_cgroup()写cpuset对应节点。这里要注意,如果cpusets_enabled为false的话,会走set_sched_policy,这部分下篇会讲到。
看看对应的fd是什么:

那我们来看看对应节点是什么内容:

然后看看对应的cpuset配置:

显然,top app 满核随便跑,foreground跑在除了3这个核以外的所有核上, 而background只能跑在小核上。

不同芯片平台配置会有差别。

② Android线程优先级和进程oom_adj

在处理app启动速度的时候,可以设置主线程的优先级,保证主线程占用的cpu足够久。进程的oom_adj,决定了当内存不够的时候,lmk会根据oom_adj的大小依次释放内存。

android中对线程等级划分如下:

设置线程的优先级分为:android 提供的api和java sdk自带的api
注意: 要使用android提供的api设置,用java提供的作用不够显着

作用: 可以在主线程设置主线层等级;在Glide加载图片的时候设置低优先级。当图片量很大的时候可以降低加载图片线程的等级

android内存不够了,会触发oom机制,lowMemoryKiller会根据每个进程的oom_adj的等级,依次杀死进程,释放内存。

lom会根据free的内存的值,来判断kill掉哪个等级下的进程。例如当空闲内存只有64M了。会kill掉oom_adj 为12-15的进程

真实案例:应用A跳到第三方应用B,在第三方应用B中播放视频,加载大量图片,导致返回的时候,应用A走了SplashActivity。通过logcat发现A应用被kill掉了

③ Android 进程管理篇(五)-调度策略与优先级

接上篇cpuset,这篇来看看进程优先级与调度策略管理。

Linux中,优先级号一共有0-139,其中0-99的是RT(实时)进程,100-139的是非实时进程。
数字越低优先级越高。

SCHED_IDLE idle状态低优先级进程调度

先看Process中调度策略的划分,与上面介绍的一样。

首先在AMS中封装了FIFO和NORMAL的两个策略,NORMAL好说,看看FIFO在哪用到

这里Process.setThreadScheler并没有太多的应用,我们直接来看优先级设置吧。else中将top app的UI线程与render线程都设置为TOP_APP_PRIORITY_BOOST优先级,nice值为-10,非常高。

这里主要调用androidSetThreadPriority方法

这里通过set_sched_policy来调整调度策略,并通过setpriority设置进程优先级。这里不特意区分进程与线程了,反正在linux中都是进程。

这里与前面的cpuset非常相似,依然是写节点,节点前面也提了就是:

那么这里又引入了一个schedtune子系统,简单介绍下:
schedtune是ARM/Linaro为了EAS新增的一个子系统,主要用来控制进程调度选择CPU以及boost触发。通过权重来分配CPU负载能力来实现快速运行。高权重意味着会享受到更好的cpu负载来处理对应的任务,换句话说你能享受相对更好的cpu运行性能。

简单梳理下schedtune和不同类型SchedPolicy之间的对应关系:

看下具体文件夹内容:

系统配置:
这里/dev/stune相关配置只做了这么一个

④ Android保活方案

系统出于性能和体验上的考虑,APP退到后台后并不会真正的kill、掉进程,而是将其缓存起来。
打开的应用越多,缓存的应用也就越多,在系统进程不足的情况下,系统根据自己的一套进程回收机制,来判断kill掉哪些进程,以腾出进程给需要的app,这套进程回收机制叫做low memory killer。

内存阀值,每个手机都不一样,当可用内存小于该值得时候,Android就会杀死对应优先级得进程。

进程的优先级通过oom_adj来判断,oom_adj取值如下:

0-3是比较安全的oom_adj一般不会被系统杀死的,所以我们只要保证自己的app oom_adj在0-3之间就可以了。
可以通过adb命令:cat /proc /4181/oom_adj来查看自己app的oom_adj的值
4181是进程号

原理:手机关闭屏幕的时候,偷偷创建一个activity,让应用成为前台进程,打开屏幕时关闭activity,这样用户就不会发现什么异常,我们知道前台应用的oom_adj为0是不会被杀死的,这样就达到看保活的目的。

缺点:activity不够干净,只有在息屏的时候才生效,存在局限性比较大,而且谷歌原生的系统息屏的时候不会清理进程,但是现在很多厂商会在息屏的时候清理内存,所以本方案的可行性不高,可以作为了解。

保活原理:启动一个前台服务,从而拉高整个应用的优先级。
因为一旦通知被用户干掉那么该保活方案就不好用了,所以通知图标存在与否是该方案是否可行的关键。
但是该方案是谷歌官方承认的保活方案,所以可行性还是很高的。
需要适配
API<18通知图标不会显示

API>=18&&API<26可以启动双服务,绑定同样的D,然后stop
这个方法的原理是8.0系统之前会根据服务的id来判断通知,那么第二个id设置跟第一个相同,然后自杀,系统就会误认为此通知已死就不会通知了,那么通知栏上面就不会显示

API>=26后暂时没有方式能够隐藏
8.0之后不可以创建同样的id的通知,所以此隐藏通知的方法就不好用了,当然了,通知显示与否不是该方案成功的评判标准,所以说还是可以用的。

在发生特定系统事件时,系统会发出广播,通过在 Androidmanifest中静
态注册对应的广播监听器,即可在发生响应事件时拉活
但是从 android7.0开始,对广播进行了限制,而且在8.0更加严格该方法就不适用了。

有多个app在用户设备上安装,只要开启其中一个就可以将其他的app也拉
活。比如手机里装了手Q、QQ空间、兴趣部落等等,那么打开任意一个app后,其
他的app也都会被唤醒

系统每隔一段时间会进行账户同步,当系统去账户同步的时候(不一定多长时间,跟系统有关),我们就去拉活app,这个方案是非常稳定的,当然了国内的系统都是定制的,所以还是需要一定的适配的。
优点:系统唤醒,比较稳定
缺点:时间不能把控

JobScheler允许在特定状态与特定时间间隔周期执行任务。可以利
用它的这个特点完成保活的功能,效果即开启一个定时器,与普通定时器不
同的是其调度由系统完成。
同样在某些ROM可能并不能达到需要的效果

⑤ Android提升服务进程优先级

在android应用开发时,我们经常会在后台开一个service,来处理一些业务操作。最近公司的一个项目就是,通过service不断地和硬件设备交互,获取数据,在页面长时间停留在一个页面时,手机的屏幕会出项锁屏的状况,这时,我们的应用的优先级就会下降,很多次,等打开屏幕的瞬间,我发现原来的原来的进程被杀死了,应用又回到了首页,尤其是在Android高版本的系统中尤为突出。所以下面我们通过提成优先级的方式,来进行进程保活

2.在程序开始的地方注册这个广播接收者

4.定义这个activity的style属性 value - style.xml 文件

5.Androidmanifest文件中注册这个activity

大功告成!
经过测试,本人的华为荣耀9i,原来存在的问题被解决了,希望大家能互相交流经验。

⑥ 进程保活

一 、问:什么是进程保活?

答:进程保活就是进程永远存在内存中,是杀不死的,就算杀死了也会有办法重新启动起来,其实这些并不是流氓手段,很多情况下,如果你想给你的用户提供服务,就必须有一个进程常驻着,便于在特定的时候做一些特定的事情,比如广播接受者,他就不支持静态注册,也就是说如果我们想接受屏幕开关启动的广播,必须要在进程中动态注册,这个时候如果没有一个常驻的进程,锁屏业务就无法正常的为用户展开服务。

二、问:进程是怎么死掉的呢?

答:其实进程被杀死的原因,一方面是人为的,二、可能被第三方应用杀死,如杀敌软件等。

三、问:Android进程的优先级?

答:

  1、前台进程 (Foreground process):用户当前操作所在的进程,当内存不足以承担前台进程的使用,才有可能回收

  2、可见进程(Visible process):没有任何前台组件,但是仍然会影响屏幕上所见内容,他是一种极为重要的进程,除非为了维持前台进程,因内存不足,有可能会回收掉可见进程,否则系统是不会回收可见进程。

  3、服务进程(Service process):他与用户所见的内容是没有直接关联,但是他们通常执行一些用户关心的操作,比如说在后台获取网络数据,后台播放音乐,后台进行一些数据计算等。被杀死的原因:也是为了

  支持前台进程和可见进程,因内存不足情况下才会被回收。

  4、后台进程(BaclGround process):对用户的体验没有直接的影响,用户可以随时终止他们,这个进程是为了供给上面三个进程来使用的,通常在后台进程运行着很多操作,他们保存在一个列表当中,为了确保用户最近查看Activit的进程最后一个被终止,他是一个LRU算法

  5、空进程(Empty process) :保存这个进程的唯一目的就是用来做缓存,以缩短下次在运行组件所需的启动时间,为了使系统总体的资源在进程缓存和内存底层之间保持平衡。它是不包括任何组件的进程.

四、问:Android进程的回收策略?

答:Android进程的回收策略主要是通过Low memory killer机制来完成的。

  Low memory killer:通过一些比较复杂的评分机制,对进程进行打分,然后讲分数的进程判定为bad进程,杀死并释放内存。Low memory killer是定时进行检查的,它主要是通过进程的OOM_ODJ来判断进程的优先级。当OOM_ODJ的值越小,进程的优先级越高,而OOM_ODJ越不会去回收。反之就会被回收。

  注意:Low memory killer和out memory不一样的地方:out memory机制只有当系统内存不足的时候才会启动检查,而Low memory killer是定时进行检查的,它主要是通过进程的OOM_ODJ来判断进程的优先级。

五、问:进程保活方案?

答:Android进程的回收策略主要是通过Low memory killer机制来完成的。

  1、利用系统广播拉活,在发生系统事件的时候,系统会发出相应的广播,

    详情查看:http://blog.csdn.NET/sunshinetan/article/details/53126857

  2、利用系统Service机制拉活,在Service有一个onStartCommand

    推荐博客:http://blog.csdn.net/wulianghuan/article/details/8596467

    Android开发的过程中,每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,然后在onStartCommand方法中做一些处理。然后我们注意到这个函数有一个int的返回值,这篇文章就是简单地讲讲int返回值的作用。从Android官方文档中,我们知道onStartCommand有4种返回值:

    START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand

    (Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。(service因内存不足的情况下,杀死的进程才可以拉活,这里要特别注意,不是所有情况都可以拉活。第一次server被杀死后,会在5秒后拉活,第二次会在10秒后,第三次会在20秒后。之后就不会在拉活。第二种情况是获得root权限通过stop停止的,也是无法通过server拉活)

    START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统将会把它置为started状态,系统不会自动重启该服务,直到startService(Intent intent)方法再次被用;。

    START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。

    START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

  3、利用Native进程拉活,

  4、利用JobScheler机制拉活:Android5.0之后提供的一个机制,他会监听主进程的存活,如果死掉就会激活拉活进程。

  5、利用账号同步机制拉活:android系统有一个账户系统,设置一个自己的账户,android会定期唤醒账户更新服务。我们可以自己设定同步的事件间隔,且发起更新的是系统,不会受到任何限制。需要在 AndroidManifest 中定义账号授权与同步服务。

    Android 版本(Android N)中系统对账户同步这里做了变动,该方法不再有效。

    缺点:

          a.用户会在系统设置的账户列表里面看到一个不认识的账户;

          b.同步的事件间隔是有限制的,最短1分钟,见源码,如果小雨60秒,置为60秒;

          c.用户可以卸载账户;

          d.必须联网!google提供这个组件是让你同步账户信息,不联网就不能保活!

⑦ android进程分为哪5种优先级顺序是怎样的

Andrid 5个进程及重要优先级前台进程>可见进程>服务进程>后台进程>空进程,
它们的回收优先级则反之

热点内容
滑板鞋脚本视频 发布:2025-02-02 09:48:54 浏览:432
群晖怎么玩安卓模拟器 发布:2025-02-02 09:45:23 浏览:557
三星安卓12彩蛋怎么玩 发布:2025-02-02 09:44:39 浏览:743
电脑显示连接服务器错误 发布:2025-02-02 09:24:10 浏览:537
瑞芯微开发板编译 发布:2025-02-02 09:22:54 浏览:146
linux虚拟机用gcc编译时显示错误 发布:2025-02-02 09:14:01 浏览:237
java驼峰 发布:2025-02-02 09:13:26 浏览:652
魔兽脚本怎么用 发布:2025-02-02 09:10:28 浏览:538
linuxadobe 发布:2025-02-02 09:09:43 浏览:212
sql2000数据库连接 发布:2025-02-02 09:09:43 浏览:726