Android 进程间通信与管理

IPC(inter-process communication)进程间通信是在不同的进程之间进行相互传递数据。

提到了进程,就不得不提一下线程与协程。

进程

进程是指正在运行中的程序抽象,是系统进行资源分配和调度的基本单元,执行进程任务的是CPU,对于Android系统来说,Android系统会在应用组件启动并且应用没有其他组件运行的时候,启动一个新的Linux进程。

主要是由三部分构成:

  • 执行指令集(描述要完成的功能)
  • 所需要的数据集合
  • 程序控制块(进程的描述信息与控制信息,是存在的唯一标志)

通俗易懂:“进程”是程序被操作系统加载到内存中运行起来后的样子

进程之间是相互独立的,一个进程崩了不会影响另一个进程,除非共享资源(IPC)

在Android 系统中,一个进程≈一个APP,也就是大多数应用也就一个进程。

一般来说,服务(Service)、 WebView(用来在 App 里嵌入网页)就会单开一个进程,防止阻塞主进程

那在Android系统中谁管理进程呢? AMS

AMS

”溥天之下, 莫非王土“

AMS作为Android系统的核心组件之一,扮演着重要的角色。它负责管理应用程序的生命周期,包括应用的启动、切换、销毁等操作。同时,AMS还负责进程调度,根据系统资源的使用情况来决定应用程序的优先级,以提高系统的整体性能。此外,AMS还负责任务栈的管理,用于管理应用程序的界面显示和切换。

AMS 具体职责

AMS具体负责的有:

  • 启动 Activity: 你点击一个 App 图标 → AMS 帮你打开对应界面
  • 管理进程: 系统决定是否启动/保留/杀死某个 App 的进程
  • 生命周期管理:例如 onPauseonResumeonStop 都是 AMS 控制的
  • 管理任务栈:每个 App 的 Activity 是如何压入/弹出的
  • 管理服务(Service) :启动/绑定服务

AMS 本质:system_server中的一个Java 服务类

是通过 Binder 机制 和 App 进行通信的,平时在 App 中调用 startActivity() 等,其实底层就是通过 Binder 跳到了 AMS。

相当于

1
2
3
4
5
6
7
8
9
10
graph TD
A[App process] -->|startActivity| B(Binder call)
B --> C[system_server process]
C --> D[AMS: ActivityManagerService]
D --> E{Target process exists?}
E -- No --> F[Zygote forks new process]
E -- Yes --> G[Send message to target App]
F --> G
G --> H[ActivityThread: scheduleLaunchActivity]
H --> I[Launch target Activity onCreate]

这是一个大概的启动Activity的图,具体还有很多,这些都牵扯到Framework层次

AMS的底层实现

从Java角度来说,AMS是一个JAVA单例类实现了IBinder接口(间接)

➡️ AMS 继承了 IActivityManager.Stub
➡️ Stub 又继承了 Binder,而 Binder 实现了 IBinder 接口

当在App中调用的时候

1
ActivityManager.getService().startActivity(...)

拿到的并不是 AMS 本体,而是它的 Binder Proxy(代理)对象,由 IActivityManager.Stub.asInterface(binder) 生成。这个 proxy 实际负责跨进程通信,把你的请求传给 system_server 中真正的 AMS 来处理

线程

线程(thread)是操作系统能够进行运算调度的最小单位,其是进程中的一个执行任务(控制单元),负责当前进程中程序的执行

每个进程启动后,至少会有一个线程运行 —— 主线程(Main Thread),它就是执行你代码的起点。

但实际上,并不是线程越多,进程的工作效率越高,这是因为在一个进程内,不管你创建了多少线程,它们总是被限定在一颗CPU内,或者多核CPU的一个核内

这意味着,多线程在宏观上是并行的,在微观上则是分时切换串行的,多线程编程无法充分发挥多核计算资源的优势

这导致使用多线程做任务并行处理时,线程数量超过一定数值后,线程越多速度反倒越慢的原因。

二者区别:

  • 本质区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
  • 在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小
  • 所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
  • 内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源
  • 包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程

协程

协程是比线程更轻量的异步任务单位,能在一个线程内挂起/恢复执行,不需要开启新线程,也能实现并发。

你可以把协程理解为:

“一个可以 暂停恢复 的小任务,它不像线程那样占资源,却可以做出线程那样的异步效果。”

和他有点像的是Handler(异步处理的工具)

IPC:

跨进程通信:Android 的系统服务(如 AMS)都运行在一个叫 system_server 的大进程里,而你的 App 是另一个进程。 所以要想让 App 跟 AMS 通信,必须通过 Binder 跨进程通信机制