一、Linux中的进程管理
在Linux中,进程是指处理器上执行的一个实例,可使用任意资源以便完成它的任务,具体的进程管理,是通过“进程描述符”来完成的,对应Linux内核中的task_struct数据结构。进程描述符,包括进程标识、进程的属性、构建进程的资源。
一个进程可以通过fork()或者vfork()调用创建出子进程,这些子进程可以访问父进程的地址空间,包括文本段、数据段、堆栈段。

通常情况下,调用fork()的进程处于task_running状态,则fork出来的子进程默认也处于task_running状态,具体来说,在fork之后、exec之前,子进程处于task_running状态中的就绪状态。

进程的运行状态包括以下几种。
1、task_running:可执行状态。包含正在CPU上执行的、可执行但是尚未被调度执行这两种子状态,后者对应就绪状态。
2、task_interruptible:可中断的睡眠状态。因为等待某事件的发生而被挂起。当等待的事件发生时,处于该状态的进程将被唤醒。
3、task_uninterruptible:不可中断的睡眠状态。处于睡眠状态,但是此刻进程是不可中断的。此时进程不响应异步信号,不能通过发送信号的方式kill之,但可以响应硬件中断,例如磁盘IO,网络IO等。
 4、task_stopped / task_traced:暂停状态或跟踪状态。处于task_traced状态的进程不能响应SIGCONT信号而被唤醒,只能等到调试进程通过ptrace系统调用执行ptrace_cont、ptrace_detach等操作,或调试进程退出,被调试的进程才能恢复task_running状态。
5、task_zombie :僵尸状态。在进程收到SIGSTOP、SIGTTIN、SIGTTOU等信号,即将终止时,会进入该状态,此时进程成为僵尸进程。该状态的进程会处理一些资源释放工作,然后发送SIG_CHLD信号给父进程。

二、Android进程管理机制
在linux系统中,应用程序执行完成后,最终会清理一些进程使用的文件描述符、释放掉进程用户态使用的相关的物理内存,清理页表,然后发送信号给父进程。但在Android系统中,应用程序执行完成后,该应用所在的进程通常还是会在后台继续运行,除非应用程序在执行完成后主动调用System.exit或者Process.killProcess之类的方法。
这样设计的好处,主要是加快应用程序再次启动的速度,改善用户体验。当内存不足时,系统会按照特定规则,包括进程优先级、占用内存等信息,来清理进程并释放对应的资源。

1、进程优先级
在Android中,进程按优先级可以分为:前台进程、可见进程、服务进程、后台进程、空进程。优先级依次降低。

1)Forground,前台进程
这种进程优先级最高,可以细分下面几种情况: 
case1:有个前台Activity,特指已经执行了onResume但还没执行onPause的Activity;
case2:有个Service且和一个前台Activity绑定的进程;
case3:调用了startForground的前台Service所在进程(这种服务会带个通知);
case4:正在执行onReceive函数的BroadcastReceiver所在进程,以及正在执行服务的生命周期方法诸如onCreate、onStartCommand的进程。

2)Visible,可见进程
可见进程没有处于前台的组件,但是用户仍然能看到进程中的组件,例如某进程的Activity调用了申请权限对话框,具体包括:
case1:有个仅onPause被调用的Activity(可见但被遮挡);
case2:进程中有个Service且和一个可见Activity绑定。
注意这里的可见Activity不包括前台Activity(否则就是前台进程了),并且这种进程在内存不足时也是可能被杀掉的。

3)Service,服务进程
服务进程是指有个通过startService方式启动的Service进程,并且不属于前面两类进程,例如MediaScannerService。

4)Background,后台进程
当前不可见的Activity所在进程属于后台进程,即它们的onStop被调用过,例如用户按下home键。
对于后台进程,系统会保存这些进程到一个LRU列表,当系统需要回收内存时,LRU中那些最近最少使用的进程将被杀死。

5)Empty,空进程
空进程不包含任何组件,当系统重新需要它们时(例如用户在别的进程中通过startActivity启动了它们),可以省去fork进程、创建Android运行环境等漫长的工作,节省时间,缓存性质。这种进程优先级最低,在任何时候都可能被杀掉。

如前所述,大部分应用是单进程的,但是进程和组件类型是高度关联的。如果应用中有生命周期差异较大的组件,考虑使用多进程分别处理。一方面是让占用资源较多的进程可以被系统及时回收,另一方面,避免那些需要长时间持续运行的任务由于组件生命周期的影响进入后台进程执行。

2、内存不足时的杀进程策略
在Linux系统中,进程的优先级对应一个参数,也就是oom_score_adj,lowmemorykiller程序会根据内存使用情况和进程优先级,动态杀进程以释放内存资源。

当内存不足或者发生oom错误时,lowmemorykiller根据特定策略先杀优先级最低的进程,然后逐步杀优先级更低的进程(同样优先级会按照内存占用情况排序),依此类推,以回收预期的可用系统资源,从而保证系统正常运转。

在Android系统中,进程的组件状态变化时,组件所在进程的优先级也会发生变化。一个典型的场景是,切换到后台的进程,其优先级低于前台进程。

App的前台/后台切换操作对oom_score_adj的影响,我们可以使用adb命令cat/proc/[pid]/oom_score_adj来查看。详细的优先级信息在ProcessList.java中有定义,对应的部分进程类型如下。

  • Cached,缓存进程,包括空进程、只有activity的后台进程,其adj在900~906;
  • B Services,无UI组件且在Lru进程表中位于后2/3的服务进程(比较旧的后台服务进程),其adj为800;
  • Previous,上一个应用进程,例如按home键进入后台的进程,其adj为700;
  • Home,也就是launcher进程,其adj为600;
  • A Services,没有UI组件且在Lru进程表中位于后2/3的服务进程(比较旧的后台服务进程),其adj为500;
  • Perceptible,有着用户可感知组件的进程,包括前台服务进程,adj为200;
  • Visible,可见进程,其adj为100;
  • Foreground,前台应用进程,其adj为0;
  • Persistent,系统常驻进程,例如systemui、phone进程,其adj为-700或-800。如果是在AndroidManifest.xml中申明android:persistent="true"的进程,adj为-800;如果是由startIsolatedProcess()方式启动或由SystemServer进程、persistent进程绑定的服务进程,则为-700;
  • System进程,典型的是SystemServer进程。
  • Native进程,例如init、surfaceflinger、mediaserver进程,其adj为-1000;

内存不足时,AMS会根据上述动态优先级信息,通过ProcessRecord,在native层给指定进程发送信号以终止进程,进而释放内存资源。相关函数包括:killProcessesBelowForeground, killProcessesBelowAdj, ProcessRecord.kill, killPids等。

(相关完整且成体系的文章,可参见本人原创的开源电子书《Android系统与性能优化》,地址:https://github.com/carylake/androidnotes)

Android进程管理机制研究的更多相关文章

  1. 【朝花夕拾】Android性能篇之(六)Android进程管理机制

    前言        Android系统与其他操作系统有个很不一样的地方,就是其他操作系统尽可能移除不再活动的进程,从而尽可能保证多的内存空间,而Android系统却是反其道而行之,尽可能保留进程.An ...

  2. Android内存进程管理机制

    参考文章: http://www.apkbus.com/android-104940-1-1.htmlhttp://blog.sina.com.cn/s/blog_3e3fcadd0100yjo2.h ...

  3. Android内存管理机制之一:low memory killer

    转载自http://www.miui.com/thread-29268-1-1.html 准备写这个专题之前,心里是有点忐忑的.首先Android内存管理机制相当复杂,想要讲清楚比较困难:其次对于绝大 ...

  4. Android包管理机制(二)PackageInstaller安装APK

    前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...

  5. Android内存管理篇 - 从updateOomAdjLocked看lowmemorykiller之外的Android进程回收机制

    提起android的进程回收机制,大家所熟知的是Android的lowmemroykiller的机制.当系统可用内存低于某个阀值时,即会杀死这个阀值对应的Adj值的所有应用.但是本篇文章并为是要介绍L ...

  6. Android 进程通信机制之 AIDL

    什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在 ...

  7. Android包管理机制(一) PackageInstaller的初始化

    前言 包管理机制是Android中的重要机制,是应用开发和系统开发需要掌握的知识点之一. 包指的是Apk.jar和so文件等等,它们被加载到Android内存中,由一个包转变成可执行的代码,这就需要一 ...

  8. Android进程回收机制LMK(Low Memory Killer)

    熟悉Android系统的童鞋都知道,系统出于体验和性能上的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来.打开的应用越多,后台缓存的进程也越多.在系统内存不足的情况下,系 ...

  9. 初探Linux进程管理机制

    转至:http://ixdba.blog.51cto.com/2895551/543737 一 .进程的概念和分类1.进程的概念 Linux是一个多用户多任务的操作系统.多用户是指多个用户可以在同一时 ...

随机推荐

  1. drf目录

    drf目录 1 web接口与restful规范 2 django中的restful规范 3 CBV请求分析 4 请求模块分析 5 响应模块分析 6 异常模块 7 解析模块 8 序列化类 9 视图组件 ...

  2. 【java】使用java.util的【Collections】简化List创建

    我们在创建一个List并往其中加入一个元素的时候一般会这么做: public List<User> getCurrentUser() { List<User> users = ...

  3. 利用tp5开发智慧软文发布系统中遇到的一些坑

    1. PHP 计算两个时间戳之间相差的时间 假设你两个时间戳为$a,$b; 你可以用$c=$a-$b;(反正就是大的减小的),这时$c就是两个时间间隔的秒数了. 想求两个时间间隔的天数就用:$c/(6 ...

  4. Tensorflow搭建CNN实现验证码识别

    完整代码:GitHub 我的简书:Awesome_Tang的简书 整个项目代码分为三部分: Generrate_Captcha: 生成验证码图片(训练集,验证集和测试集): 读取图片数据和标签(标签即 ...

  5. Python 中如何实现参数化测试?

    Python 中如何实现参数化测试? 之前,我曾转过一个单元测试框架系列的文章,里面介绍了 unittest.nose/nose2 与 pytest 这三个最受人欢迎的 Python 测试框架. 本文 ...

  6. ASP.NET Core 选项模式源码学习Options IOptions(二)

    前言 上一篇文章介绍IOptions的注册,本章我们继续往下看 IOptions IOptions是一个接口里面只有一个Values属性,该接口通过OptionsManager实现 public in ...

  7. JsonSchmea用法

    JsonSchmea用法 简介 JSON Schema是基于JSON格式,用于定义JSON数据结构以及校验JSON数据内容. JSON Schema官网地址:http://json-schema.or ...

  8. mybatis注解

    @select查詢 @insert添加 @delete刪除 @update修改 @Results自关联 @Results映射 @One UserByRole表: RoleByUser表: @Many ...

  9. [TimLinux] CSS 纯CSS实现动画展开/收起功能

    内容转自CSS世界,理解之后进行了简化,简化后代码: <!DOCTYPE html> <html> <head> <meta charset=utf-8 /& ...

  10. Seata 客户端需要同时启动 TM 和 RM 吗?

    在分析启动部分源码时,我发现 GlobalTransactionScanner 会同时启动 RM 和 TM client,但根据 Seata 的设计来看,TM 负责全局事务的操作,如果一个服务中不需要 ...