深入AMS源码(四)——ActivityManagerService的进程管理

2023-10-27

1、AMS中的进程管理

final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>(); 

在AMS的内部属性中使用mLruProcesses集合保存所有的进程信息,AMS将所有进程按照优先级从低到高的顺序保存着对应的ProcessRecord信息,即排在前面的进程优先级越低,当系统内存不足时优先被Killer杀死;

在AMS的工作过程中,会不断调用updateLruProcessLocked()方法进行进程排序,在mLruProcesses()中保存按照以下规则保存数据
在这里插入图片描述
在AMS中越重要的进程会放在mLruProcesses集合的最后面,正在使用交互的进程会保存在最后,然后按照其他进程、Service进程、Activity进程的顺序重要行逐步增加,Activity进程的重要性最高,为了区分各个进程的位置,AMS中引入mLruProcessServiceStart和mLruProcessActivityStart变量保存二者的起始位置,在添加时当进程中包含活动则添加到mLruProcessActivityStart之后,如果不包含活动但包含Service服务,则添加到mLruProcessServiceStart之后;

  • updateLruProcessLocked源码
final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
            ProcessRecord client) {
   
        final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities
                || app.treatLikeActivity || app.recentTasks.size() > 0;//1、
        final boolean hasService = false; 
        if (!activityChange && hasActivity) {
    // 如果activityChange为false则无需改变位置
            return;
        }

        mLruSeq++; // 更新编号
        final long now = SystemClock.uptimeMillis();
        app.lastActivityTime = now; // 保存更新的时间

        if (hasActivity) {
    // 如果包含Activity,
            final int N = mLruProcesses.size();
            if (N > 0 && mLruProcesses.get(N-1) == app) {
    
                return;
            }
        } else {
   
            if (mLruProcessServiceStart > 0 // 不包含Activit但已经存在其他段的最末尾,也无需更新
                    && mLruProcesses.get(mLruProcessServiceStart-1) == app) {
   
                return;
            }
        }

        int lrui = mLruProcesses.lastIndexOf(app); // 获取目前位置的index
        if (app.persistent && lrui >= 0) {
   
            return;
        }
        if (lrui >= 0) {
    
            if (lrui < mLruProcessActivityStart) {
    // 如果index小于mLruProcessActivityStart,则Activity段前移一位
                mLruProcessActivityStart--;
            }
            if (lrui < mLruProcessServiceStart) {
   //如果index小于mLruProcessServiceStart,则Activity段前移一位
                mLruProcessServiceStart--;
            }
            mLruProcesses.remove(lrui); //移除原来的app信息
        }

        int nextIndex; // 
        if (hasActivity) {
   
            final int N = mLruProcesses.size();
            if ((app.activities.size() == 0 || app.recentTasks.size() > 0)
                    && mLruProcessActivityStart < (N - 1)) {
   
                mLruProcesses.add(N - 1, app); // 如果进程不存在活动,但recentTasks存在任务则添加到最后位置
                final int uid = app.info.uid;
                for (int i = N - 2; i > mLruProcessActivityStart; i--) {
   
                    ProcessRecord subProc = mLruProcesses.get(i);
                    if (subProc.info.uid == uid) {
    // 遍历集合中进程,匹配uid相等的进程
                        if (mLruProcesses.get(i - 1).info.uid != uid) {
   //处理其他进程,将该用户进程前移,其他进程后移
                            ProcessRecord tmp = mLruProcesses.get(i);
                            mLruProcesses.set(i, mLruProcesses.get(i - 1));
                            mLruProcesses.set(i - 1, tmp);
                            i--;
                        }
                    } else {
   
                        break;
                    }
                }
            } else {
   
                mLruProcesses.add(app); // 直接添加进程信息
            }
            nextIndex = mLruProcessServiceStart;
        } else if (hasService) {
    存在Service服务
            mLruProcesses.add(mLruProcessActivityStart, app); // 保存在Service服务的开始位置
            nextIndex = mLruProcessServiceStart;
            mLruProcessActivityStart++; // mLruProcessActivityStart后移
        } else  {
   
            int index = mLruProcessServiceStart;
            if (client != null) {
   
                int clientIndex = mLruProcesses.lastIndexOf(client);//获取当前客户端最高级的位置
                if (clientIndex <= lrui) {
   
                    clientIndex = lrui; // 如果最高级小则赋值最高级为lrui
                }
                if (clientIndex >= 0 && index > cli
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入AMS源码(四)——ActivityManagerService的进程管理 的相关文章

  • Linux进程管理-ps

    Linux进程管理 ps ps 命令的基本格式如下 xff1a root 64 localhost ps aux 查看系统中所有的进程 xff0c 使用 BS 操作系统格式 root 64 localhost ps le 查看系统中所有的进
  • AMS-1117

    电路图 说明 10uF 61 10622uF 61 226100nF 61 104106 61 10乘以10的6次方pF xff1b 简单点的说就是106表示容量 10后面加六个零 单位pF 转换成uF就是10uF 电容之间的换算公式 xf
  • 进程管理(五)--linux进程内核栈

    在进程创建时 xff0c 内核会为进程创建一系列数据结构 xff0c 其中最重要的就是上章学习的task struct结构 xff0c 它就是进程描述符 xff0c 表明进程在生命周期内的所有特征 同时 xff0c 内核为进程创建两个栈 x
  • Android 12 源码下载、编译与烧录到Pixel 3a

    android 12 源码下载 编译与烧录到Pixel 3a 当前设备环境 源码下载 温馨跳转 个人总结源码下载 谷歌手机设备驱动的下载 编译 烧录 当前设备环境 操作系统 ubuntu 18 04 LTS 手机 谷歌手机Pixel 3a
  • Android显示系统 SurfaceFlinger内部机制 3 APP申请创建Surface的过程

    韦东山 笔记 3 APP申请创建Surface的过程 看看Surface test的过程 1 获取SF服务 2 创建Surface 3 得到buffer 4 写buffer 5 回顾下获取SF服务过程 AP获取SF服务 调用createCo
  • supervisor系列:2、运行supervisor

    supervisor系列 2 运行supervisor 文章目录 supervisor系列 2 运行supervisor 1 添加一个程序 2 运行supervisord 2 1 supervisord命令行配置 3 运行superviso
  • 从源码出发浅析 Android TV 的焦点移动原理(下篇)

    转自 https cloud tencent com developer article 1006297 2 2 findNextFocus 如果开发者没有指定nextFocusId 则用findNextFocus找指定方向上最近的视图看一
  • Android zygote进程启动过程

    zygote启动过程中涉及到以下模块 app process zygote USAP socket FileDescriptor FD AndroidRuntime AppRuntime 定义于app process模块 继承自Androi
  • Android 13 - binder阅读(5)- 使用ServiceManager注册服务2

    上一篇笔记我们看到了binder transaction 这个方法很长 这一篇我们将把这个方法拆分开来看binder transaction做了什么 从而学习binder是如何跨进程通信的 1 binder transaction stat
  • Android数据的四种存储方式

    Android数据的四种存储方式 SharePreferences SQLite Contert Provider File 网络存储 作为一个完整的应用程序 数据存储的操作是必不可少的 Android系统提供了四种存储数据方式 分别为 S
  • FBE中的Home界面FallbackHome

    FallbackHome FallbackHome继承Activity 是安卓系统启动后未解锁时的home界面 Settings程序AndroidManifest xml中定义了FallbackHome的intent filter 可以看到
  • android面试题-ActivityRecord TaskRecord和ProcessRecord之间的关系

    转自 http blog csdn net mwq384807683 article details 72529285 源码分析相关面试题 Volley源码分析 注解框架实现原理 okhttp3 0源码分析 onSaveInstanceSt
  • Linux的进程管理

    目录 1 概述 2 进程描述符 2 1 进程描述符的分配 2 2 进程描述符的存放 2 3 进程状态 2 4 进程上下文 2 5 进程家族树 3 进程的创建 4 进程的终结 5 线程的实现 1 概述 进程是执行期的代码 但是进程不止包括这样
  • 深入AMS源码(二)—— ActivityManagerService对Activity的调度管理

    1 概述 在上一篇深入AMS源码 一 ActivityManagerService的基础知识文章介绍了AMS的基础信息 主要包括AMS中主要的数据结构 主要功能类和属性以及AMS中对生命周期的调度方式 本篇主要从源码的角度分析下AMS对Ac
  • 从setContentView到onResume应用显示过程分析

    之前总体笼统地分析了Acitivity从启动到显示的过程 Activty启动到显示的过程 一 Activty启动到显示的过程 二 发现很多细节没有注意到 后续挑些过程中比较重要的部分重点分析 在上一篇文章分析了一个app从zygote到on
  • Android中so使用知识和问题总结以及插件开发过程中加载so的方案解析

    转自 https blog csdn net jiangwei0910410003 article details 52312451 一 前言 Android中有时候为了效率以及平台开发库的支持 难免会用到NDK开发 那么都会产生一个so文
  • Android图形显示系统4 图像生产者(下)

    一 概述 在上一篇文章 Android图形显示系统2 图像消费者 中 我们详细地讲解了图像消费者 我们已经了解了 Android 中的图像元数据是如何被 SurfaceFlinger HWComposer 或者 OpenGL ES 消费的
  • Android 13 - binder阅读(6)- 使用ServiceManager获取服务

    最近事情好多 使用ServiceManager获取服务就暂时先不学习了 不过从之前的学习中我们也大致可以猜到使用ServiceManager获取服务的过程 根据服务名称获取到ServiceManager中服务代理对应的Handle 再到Bi
  • 从zygote到onCreate应用启动过程分析

    在之前的文章讲了app进程大概的启动过程 https blog csdn net qq 36063677 article details 125638137 这篇文章细致的分析一下app进程从zygote进程fork出来到onCreate等
  • Android 12读写存储卡权限申请

随机推荐

  • Word‘由于宏安全设置 无法找到宏’问题解决

    针对这个问题 尝试试很多网上的做法无果后 意外发现是自己电脑的杀毒软件把该文件误认为是病毒隔离起来 只需将其恢复到信任区即可 若仍无法解决 检查word是否启用宏
  • 我靠TikTok抖音赚到了人生第一桶金:这个风口行业,真的很赚钱

    现代人的 懒 简直超乎你想象 吃饭靠外卖 买东西靠快递 凡是一切你能想到的 麻烦 现代科技都能替你搞定 而这 恰恰是一种新型的赚钱方式 十年前的淘宝被人嘲笑 说这是马云的异想天开 十年后的淘宝 拼多多 京东告诉你 这一切都已成真 而且带着一
  • 虚拟机迁移原理

    我们常常遇到需要迁移虚拟机的问题 比如需要维护某台设备 会将设备上的一切应用迁移到另一台设备 但是如何将虚拟机进行迁移呢 好比说 虚拟机中正在运行一个程序 这个程序有源源不断的数据访问 怎么使得在不影响这些访问的情况下把虚拟机迁移到领一台服
  • C语言图形库——EasyX常用函数

    上节讲到贴出一张图片的过程 本节接着介绍一些基本的图形库函数 头文件 include
  • 深入浅出SSD--5.1PCIE基础知识

    深入浅出SSD 5 1PCIE基础知识 1 关于PCIE的速度 SSD使用PCIe接口比SATA快 下面是PCIE1 0 2 0 3 0速度 表中的带宽 比如PCIe3 0 1 带宽为2GB s 是指双向带宽 即读写带宽 如果单指读或者写
  • 本周最新文献速递20220522

    本周最新文献速递20220522 一 精细解读文献 一 文献题目 Single nucleus chromatin accessibility profiling highlights regulatory mechanisms of co
  • xml转换word文档

    点击下载 download value flag let this this this axios method get url url lengthMeasurementTwice params machineId this machin
  • http请求头origin、referer和host区别

    1 Host 描述请求将被发送的目的地 包括且仅仅包括域名和端口号 HTTP 1 1 的所有请求报文中必须包含一个Host头字段 且只能设置一个 2 Origin 请求头origin表明了请求来自于哪个站点 包括且仅仅包括协议 域名和端口
  • 创维机顶盒E900刷LinuxNas系统

    家里有一个一直没用的创维E900的机顶盒 芯片是海思 hi3798v100 的 本着废物利用的原则 我想将他刷成linux 没想到网上真的有教程 https histb com 我看了一下 以我现在的技术 问题不大 大不了变砖罢了 反正都是
  • js 中数字小数点末尾的0显示与否

    js 中数字小数点末尾的0显示与否 不显示0 显示0 数字格式化 不显示0 我们先来看一道例题 然后围绕其展开 零 的讨论 问题 得到一个随机数组成的数组 数组长度为10 结果类似于 0 243 0 162 0 701 0 501 此处封装
  • Learn OpenGL with Qt——模型加载:Qt搭建Assimp环境

    如果你是中途开始学习本教程的 即使你对OpenGL已经非常熟悉 请至少了解以下几个章节 因为Qt中提供了OpenGL的很多便捷操作 熟悉这些操作可以让我们在Qt中高效的使用OpenGL进行绘图 创建OpenGL窗口 着色器程序以及着色器的创
  • 如何克服看到别人优于自己而感到的焦虑和迷茫?

    文章目录 每日一句正能量 前言 简述自己的感受 怎么做 如何调整自己的心态 后记 每日一句正能量 行动是至于恐惧的良药 而犹豫 拖延 将不断滋养恐惧 前言 虽然清楚知识需要靠时间沉淀 但在看到自己做不出来的题别人会做 自己写不出的代码别人会
  • 使用Java显示图片

    之前学习C和C 时总是和数据打交道 也许是学的浅薄的关系 当时觉得显示界面和图像是如此的神秘 如今学习了一段时间的Java 发现其实界面什么的也不是那么的难懂 下面写一个简单的例子 让我们的java为我们展示张图片来看看吧 面板源码 jav
  • [LLVM教程]LLVM之第一个语言前端

    目录 LLVM教程 LLVM之第一个语言前端 LLVM教程 LLVM之第一个语言前端 万花筒 介绍与词法分析器 LLVM Tutorial Table of Contents LLVM 17 0 0git documentation LLV
  • 统计学习方法EM课后答案

    https sine x com statistical learning method 第9章 em算法及其推广 https blog csdn net weixin 35479108 article details 87894136 h
  • STM32入门——外部中断

    中断系统概述 中断 在主程序运行过程中 出现了特定的中断触发条件 中断源 使得CPU暂停当前正在运行的程序 转而去处理中断程序 处理完成后又返回原来被暂停的位置继续运行 中断优先级 当有多个中断源同时申请中断时 CPU会根据中断源的轻重缓急
  • Cannot read property 'newLine' of undefined

    angularjs报错 ERROR in src main ts Module build failed TypeError Cannot read property newLine of undefined at Object getNe
  • GitLab(Gitee)配置SSH key

    1 我们已经有了gitlab的账户 项目组已经将我们添加到了group 2 打开git bash 输入命令 ls al ssh 如果显示如下图 则表示生成过key 可以去执行第4个步骤 否则的话执行第三个步骤生成key 3 输入命令 ssh
  • 快乐的强化学习1——Q_Learning及其实现方法

    快乐的强化学习1 Q Learning及其实现方法 学习前言 简介 Q Learning算法的实现 具体实现代码 GITHUB下载连接 学习前言 刚刚从大学毕业 近来闲来无事 开始了机器学习的旅程 深度学习是机器学习的重要一环 其可以使得机
  • 深入AMS源码(四)——ActivityManagerService的进程管理

    1 AMS中的进程管理 final ArrayList