android framework层 Framework层概念

上一篇文章从原生的角度解释了Android进程管理的相关概念。本文将继续从上层框架中的进程启动、销毁场景和优先级处理,一步步分析Android进程管理的其他关键要素,以及它们与四个组件的关系。流程的开始Android框架层运行在ART虚拟机上,不具备为一般Java进程主动创建进程的能...

上一篇文章从原生的角度解释了Android进程管理的相关概念。本文将继续从上层框架中的进程启动、销毁场景和优先级处理,一步步分析Android进程管理的其他关键要素,以及它们与四个组件的关系。

流程的开始

Android框架层运行在ART虚拟机上,不具备为一般Java进程主动创建进程的能力。我们都知道Android有四大组件:Activity、Service、BroadcastReceiver和ContentProvider。那我们为什么要分他们呢?其中一个主要原因是,在四大组件的启动阶段,如果主机进程没有运行,那么系统服务进程system_server会先拉起进程,然后继续启动组件。简而言之,因为AMS封装了Android中进程的创建、销毁和优先级,所以应用端的开发者可以在不知道进程的情况下同时使用这四个组件。

启动组件的四种方法startActivity、SendBroadcast、startService/Bindservice和getContentProviderImpl可以启动进程,因为它们都向AMS发送binder消息。当AMS发现xml声明的进程中没有启动相应的组件时,会先拉起进程,然后启动相应的组件。

换句话说,四个组件就是APP流程的入口。他们都以相同的方式启动流程。基本流程:

Zygote进程启动,初始化虚拟机及基本环境,同时进入一个无限循环,提供创建 java 进程服务AMS 通过调用 Process.start() 方法,发送 socket 信息到 Zygote 进程Zygote 进程处理消息,并通过fork创建应用进程应用进程反射调用 ActivityThread.***in 方法,进入自身逻辑 (初始化 Looper/Binder 等主要服务 )AMS 创建进程成功后,会将进程以 ProcessRecord 的形式进行封装、管理。

Egg:一个实用的与流程相关的adb命令

实时创建和销毁Java进程

adb logcat -b events | grep proc**07-16 14:19:23.357 4774 4800 I am_proc_start: [0,30314,10063,com.koushikdutta.vysor,activity,com.koushikdutta.vysor/.StartActivity]07-16 14:19:23.375 4774 6027 I am_proc_bound: [0,30314,com.koushikdutta.vysor]07-16 14:19:31.621 4774 5281 I am_proc_***d: [0,30314,com.koushikdutta.vysor,900,17]

获取组件在应用过程中的详细信息。

adb shell dumpsys activity p <packageName>*APP* UID 10115 ProcessRecord{4114d9d ***87:com.ss.android.ugc.aweme/u0a115} user #0 uid=10115 gids={50115, 20115, 9997, 3002, 3003, 3001} requiredAbi=armeabi-v7a instructionSet=arm class=com.ss.android.ugc.aweme.app.host.HostApplication ... // adj, procState优先级信息 oom: ***x=1001 curRaw=0 setRaw=0 cur=0 set=0 curSchedGroup=2 setSchedGroup=2 systemNoUi=false trimMemoryLevel=0 curProcState=2 repProcState=2 pssProcState=5 setProcState=2 ... **Activities**: - ActivityRecord{5e38d19 u0 com.ss.android.ugc.aweme/.***in.MainActivity t948} **Services**: - ServiceRecord{13f23bc u0 com.ss.android.ugc.aweme/com.tt.miniapphost.process.base.HostCrossProcessCallService} ... **Connections**: - ConnectionRecord{77ae579 u0 CR com.ss.android.ugc.aweme/com.ss.android.socialbase.downloader.downloader.IndependentProcessDownloadService:@30b4240} ... **Published Providers**: - com.umeng.message.provider.MessageProvider -> ContentProviderRecord{76d000a u0 com.ss.android.ugc.aweme/com.umeng.message.provider.MessageProvider} ... **Connected Providers**: - c887614/com.android.providers.settings/.SettingsProvider->***87:com.ss.android.ugc.aweme/u0a115 s1/1 u0/0 +19h23m3s147ms - c4d7fba/com.android.providers.media/.MediaProvider->***87:com.ss.android.ugc.aweme/u0a115 s0/1 u1/2 +1m10s935ms **Receivers**: - ReceiverList{4afbc5 ***87 com.ss.android.ugc.aweme/10115/u0 remote:687d23c} ...

获取应用优先级信息

adb shell dumpsys activity oProc 0: fore T/A/TOP trm: 0 ***87:com.ss.android.ugc.aweme/u0a115 (top-activity) oom: ***x=1001 curRaw=0 setRaw=0 cur=0 set=0 state: cur=TOP set=TOP lastPss=268MB lastSwapPss=0.00 lastCachedPss=0.00 cached=false empty=false hasAboveClient=false

流程的优先级

Android框架中有两个进程优先级的度量单位。除了adj (oom_score_adj对应lmk)之外,还增加了一个新的procState变量。这两个优先事项相辅相成。adj更多用于判断是否应该为lmk杀死进程,而procState更多用于为框架层的服务“分级”进程状态。比如AMS可以通过判断procState是否小于等于process _ state _ important _ foreground来简单粗暴地判断进程是否为“前台进程”:

[ActivityManagerService.java]

@Overridepublic?boolean?isAppForeground(int?uid)?{????synchronized?(this)?{????????UidRecord?uidRec?=?mActiveUids.get(uid);????????if?(uidRec?==?null?||?uidRec.idle)?{????????????return?false;????????}????????return?uidRec.curProcState?<=?ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;????}}

这里的UidRecord是Android常用的权限管理方案。如果不修改,普通应用创建的进程都在同一个uid里。在系统端,Android经常使用uid来确定相应的进程是否有相应的优先级。

关于Android中adj和procState具体值的含义,可以查看文末的附录表。具体场景仅供参考。如果需要仔细判断当前进程的优先级状态,分析源代码是最直观的。

adj、schedGroup、procState、adjType的核心计算步骤是通过AMS中的computeOomAdjLocked方法完成的,如图:

这个方法的核心执行不外乎以下几个函数:

首先检查该进程是否处于高优场景中,如前台Activity、正在运行RemoteAni***tion,正在处理广播和Service等该进程是否是某种特殊进程,如Home,height weight和backup是否存在进程因为service和content provider互相绑定提升优先级的情况如果都不是上述情况,处于的优先级都比较低,最低的是cache进程,AMS对系统整体cache进程个数有阈值限制,超过上限就会触发清理操作

鸡蛋:用框架中的“自相矛盾”来维持它们的生命

Keep-alive无非是普通应用对操作系统的一种攻击方式。至于一般的攻击方式,我理解为利用开发者建立的规则漏洞,突破普通用户原有权限的行为。

例如,缓冲区溢出利用了旧版本C编译器在切换函数堆栈时未能有效检查堆栈信息范围的漏洞。使得普通的应用程序用户可以使用超长的栈内信息来覆盖和调整原有的栈跳转信息,应用程序可以执行其他意外的程序。这样就可以获得root权限;再比如TCP劫持,利用发送方和接收方没有好的SEQ和ACK序列的验证手段,让中间方通过控制SEQ和ACK的值来控制正常通信方的流量。

方法1: bindService相互绑定以提高优先级。

有两种优先级模式。

第一种是依赖高优先级客户端:

if?(***yBeTop?&&?procState?>?ActivityManager.PROCESS_STATE_TOP)?{????switch?(procState)?{????????case?ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:????????case?ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:????????????//?Something?else?is?keeping?it?at?this?level,?just?leave?it.????????????break;????????case?ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:????????case?ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:????????case?ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:????????case?ActivityManager.PROCESS_STATE_SERVICE:????????????procState?=?ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;????????????app.adjType?=?***yBeTopType;????????????app.adjSource?=?***yBeTopSource;????????????app.adjTarget?=?***yBeTopTarget;????????????...????}}

也许托普是真的。需要ContentProvider或服务的客户机在前台显示活动。

同样,通过允许用户选择这个客户端来提供服务,例如WallPaperService,可以使system_server成为一个客户端,从而提高进程的优先级。

第二,两个过程相互关联:

if?((cr.flags&Context.BIND_FOREGROUND_SERVICE)?!=?0)?{????clientProcState?=????????????ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;}?else?if?(mWakefulness????????????????==?PowerManagerInternal.WAKEFULNESS_AWAKE?&&????????(cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)????????????????!=?0)?{????clientProcState?=????????????ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;}?else?{????clientProcState?=????????????ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;}...if?(procState?>?clientProcState)?{????procState?=?clientProcState;????if?(adjType?==?null)?{????????adjType?=?"service";????}}

通过设置标志,两个普通的进程可以互相“攀比”来提高优先级。

2.监控锁屏广播拉起活动,监控解锁广播破坏活动:

具体步骤:

启动一个Service,通过动态广播receiver接收锁屏、开屏广播灭屏时,启动Activity到前台开屏时,将Activity进行 finish,确保用户无感知adb shell ps | grep <pacakgeName>ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes) All known processes: *APP* UID 100*** ProcessRecord{f59eb2f 30917:com.bytedance.gcsuppression.demo/u0a***} ... oom: ***x=1001 curRaw=100 setRaw=100 cur=100 set=100 curSchedGroup=1 setSchedGroup=1 systemNoUi=false trimMemoryLevel=0 curProcState=5 repProcState=5 pssProcState=5 setProcState=5 lastStateTime=-23s716ms

(该方法在Android 8.0上测试后仍然有效,但更高版本未测试;因为它利用了服务和动态广播的特性,所以框架很难响应这个逻辑,除非它在系统端维护一个服务黑名单)

过程的清理

虽然杀人过程中花样繁多,但常见的方式有三种:

名称清除触发场景函数kill具有最细的粒度,用于杀死单个java进程,如进程***、AMS杀死单个缓存进程等。普通应用也可以通过AM服务调用杀死系统中的后台进程。force-stop以包为单位,强制杀死与包关联的进程并禁止包下的大部分进程自我杀死,关闭并销毁相关组件。

常见的查杀方法,如kill、killBackground等,只查杀单个进程或部分进程。当进程死亡时,AMS将通过死亡回调得到通知,因为binder fd的释放,进程已经死亡。在此期间,AMS还可能因为服务和其他组件而再次启动流程。考虑到拉活模式的多样性,应用程序中的其他java进程或C进程仍然可以通过启动组件来再次拉起进程。

在一般的原生机器上,虽然很少使用强制停止,但通常只通过设置中的“强制停止”按钮触发。除了杀死进程,组件等信息也会被销毁,PMS中对应包名的状态也会被改变,避免再次被激活。其主要功能如下:

彩蛋:当我们滑动应用卡的时候,Android在做什么?

systemui 进程中的 com.android.systemui/.recents.RecentsActivity 接收到卡片滑动事件systemui 获取到 AMS 服务,再调用 am.removeTask 方法来移除 Task 和杀死显示该界面的进程;注意这个方法普通应用是没有调用权限的。最后通过 AMS 的 cleanUpRemovedTaskLocked 方法来杀死进程,这个方法的具体实现如下:void?cleanUpRemovedTaskLocked(TaskRecord?tr,?boolean?killProcess,?boolean?removeFromRecents)?{????//?1.?在最近任务中移除?Task????if?(removeFromRecents)?{????????mRecentTasks.remove(tr);????}????...????//?2.?选择需要查杀的进程????final?String?pkg?=?component.getPackageName();????ArrayList<ProcessRecord>?procsToKill?=?new?ArrayList<>();????ArrayMap<String,?SparseArray<ProcessRecord>>?p***p?=?mService.mProcessNames.getMap();????for?(int?i?=?0;?i?<?p***p.size();?i++)?{????????SparseArray<ProcessRecord>?uids?=?p***p.valueAt(i);????????for?(int?j?=?0;?j?<?uids.size();?j++)?{????????????ProcessRecord?proc?=?uids.valueAt(j);????????????...????????????//?2.1?如果?Task?所在进程还有别的?Task?在最近任务中显示,那么该进程不会被杀????????????for?(int?k?=?0;?k?<?proc.activities.size();?k++)?{????????????????TaskRecord?otherTask?=?proc.activities.get(k).getTask();????????????????if?(tr.taskId?!=?otherTask.taskId?&&?otherTask.inRecents)?{????????????????????return;????????????????}????????????}????????????//?2.2?进程有前台service的不会被杀,典型的有音乐播放软件????????????if?(proc.foregroundServices)?{????????????????return;????????????}????????????//?Add?process?to?kill?list.????????????procsToKill.add(proc);????????}????}????//?3.?正式查杀????for?(int?i?=?0;?i?<?procsToKill.size();?i++)?{????????ProcessRecord?pr?=?procsToKill.get(i);????????//?如果满足这两个条件才会立即被杀????????if?(pr.setSchedGroup?==?ProcessList.SCHED_GROUP_BACKGROUND????????????????&&?pr.curReceivers.isEmpty())?{????????????pr.kill("remove?task",?true);????????}?else?{????????????pr.waitingToKill?=?"remove?task";????????}????}}

鸡蛋:反生存的终结者

Android中杀死进程的最强武器是force-stop,它本质上是通过遍历所有与应用程序相关的Java进程来杀死它们:

private?final?boolean?killPackageProcessesLocked(String?packageName,?int?appId,????????int?userId,?int?minOomAdj,?boolean?callerWillRestart,?boolean?allowRestart,?boolean?doit,?boolean?evenPersistent,?String?reason)?{????ArrayList<ProcessRecord>?procs?=?new?ArrayList<>();????final?int?NP?=?mProcessNames.getMap().size();????for?(int?ip=0;?ip<NP;?ip++)?{????????SparseArray<ProcessRecord>?apps?=?mProcessNames.getMap().valueAt(ip);????????final?int?NA?=?apps.size();????????for?(int?ia=0;?ia<NA;?ia++)?{????????????ProcessRecord?app?=?apps.valueAt(ia);????????????...????????????//?continue?if?the?process?do?not?need?to?kill????????????app.removed?=?true;????????????procs.add(app);????????}????}????int?N?=?procs.size();????//?force-stop?的本质是通过遍历所有与应用有关的进程,依次查杀来实现杀死所有进程的????for?(int?i=0;?i<N;?i++)?{????????removeProcessLocked(procs.get(i),?callerWillRestart,?allowRestart,?reason);????}????updateOomAdjLocked();????return?N?>?0;}

要做反保活,只需要在removeProcessLocked的遍历之前,通过发送信号将java进程和C进程一起挂在同一个cgroup中,然后通过循环依次杀死所有进程。这种方法基本上可以消除所有的拉活方案。

摘要

进程管理与每个人的日常开发息息相关,也是Android系统中举足轻重的模块。相信通过本系列的两篇文章,我们已经对进程启动涉及的fork、进程优先级管理涉及的adj、进程的调度等概念有了更深入的了解。

本文来自又何必自找失落╮投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/625457.html

打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
() 0
上一篇 07-08
下一篇 07-08

相关推荐

  • 网站建设的概念是什么,建站流程及步骤

    大家好,欢迎收看边肖的文章。您的支持是边肖最大的动力。如果你喜欢边肖的文章,请给边肖一个赞!每个企业都需要有自己的网站。很多老板觉得建一个网站很难。其实建一个网站并没有那么难。今天,我将一步步教你如何建立自己的网站。第一步:确定网站类型首先,确定网站类型。

    2023-07-29 06:58:01
    938 0
  • 数据挖掘概念与技术第三版pdf 数据挖掘原理与算法第三版

    前不久我们的推荐算法还不够精准?让知识图谱解决”和“如何将知识图谱特征学习应用于推荐系统”的系列文章受到了同学们的广泛欢迎。大家都很关心推荐系统及其相关的底层数据挖掘技术。为了帮助朋友们更好地学习相关内容,我们邀请了微软亚洲研究院社会计算组研究员张福正为大

    2023-07-28 06:09:01
    984 0
  • 团队是什么概念 团队最重要的三要素

    什么是团队?团队是由员工和管理层组成的共同体,合理利用每个成员的知识和技能,共同努力解决问题,实现共同的目标。也可以是小团体,一个人带领4、5个人!从而实现1+1 >: 2什么是团队精神?所谓团队精神,简单来说就是大局意识、合作精神、服务精神的集中体现。团队精神是建

    2023-07-27 22:18:01
    456 0
  • 群体凝聚力是一个什么的概念

    群体凝聚力是一个中性的概念。群体凝聚力是作用于群体成员使之保持在群体内的力量,是群体发展水平的指标。高凝聚力群体成员表现的心理感受是对群体的认同感、归属感和力量感。产生的条件有:群体成员的目标一致、志趣相投、心理相容和互补,以及外界的压力与威胁等。对绩效的

    2023-07-27 21:43:01
    686 0

评论列表

联系我们

在线咨询: QQ交谈

邮件:admin@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信