通过ActivityManager跨进程通信过程理解binder通信机制


前言

例如:新手在学习使用binder机制跨进程通信时总觉得容易混淆,本文通过举例的方式来帮助理解binder通信机制。节省时间可以直接看最后总结。

一、ActivityManagerService 类

在Android系统框架中,ActivityManagerService 类是一个非常关键的系统服务类,它继承自 IActivityManager.Stub。这里的解释如下:

  1. ActivityManagerService:这是Android系统服务层的一个核心服务,它负责管理整个系统的Activity(活动)以及相关的进程、任务栈等。它负责启动、停止、恢复、销毁Activity,管理应用进程的生命周期,处理屏幕方向改变、内存不足时的进程回收等工作,是Android应用框架中的重要部分。

  2. IActivityManager.Stub:在Android系统中,为了实现在不同的进程间进行方法调用,采用了Binder IPC机制。IActivityManager.Stub 是定义在AIDL文件中生成的一个接口的本地 Binder 实现类。AIDL(Android Interface Definition Language)用于定义跨进程的接口。

当我们说 ActivityManagerService 继承自 IActivityManager.Stub,意味着 ActivityManagerService 实现了 IActivityManager 接口中定义的所有方法,使得其他进程(比如APP进程)可以通过Binder机制调用 ActivityManagerService 中提供的服务功能,如启动Activity、查询进程信息等。所以,ActivityManagerService 作为服务端,通过继承 IActivityManager.Stub 来暴露一系列系统服务接口给客户端(通常是应用程序框架层的 ActivityManager 或者是直接使用 IActivityManager 接口的应用代码)。这样就形成了一个跨进程通信的模型,使得应用程序可以与系统服务进行交互,进而操控Activity的生命周期和其他系统级别的操作。

二、ActivityManager 和 ActivityManagerService 的关系

1.运行位置

  1. ActivityManager:运行在应用程序进程中,通常是指每一个使用到 ActivityManager 功能的 Android 应用程序的进程。当开发者的应用程序调用 Context.getSystemService(Context.ACTIVITY_SERVICE) 来获取 ActivityManager 时,系统返回的是一个 ActivityManager 类的实例,但实际上它是一个代理类 ActivityManagerProxy,这个代理类运行在客户端(应用)进程中。
  2. ActivityManagerProxy:是运行在客户端进程中的一个代理类,它实现了IActivityManager接口,并通过Binder机制与ActivityManagerService进行通信。当应用程序通过Context.getSystemService(Context.ACTIVITY_SERVICE)获取到ActivityManager实例时,得到的实际上是ActivityManagerProxy对象。此代理对象封装了对ActivityManagerService的调用,当应用程序调用ActivityManager的方法时,实际上是通过Binder通信机制向ActivityManagerService发送请求。
  3. ActivityManagerService:运行在系统服务进程(system_server)中,它是一个系统服务,属于 Android 框架层的一部分。system_server 进程包含了多个核心系统服务,ActivityManagerService 就是其中之一,它负责管理所有与 Activity 相关的操作,如启动、停止、调度 Activity,管理应用进程的生命周期等。

2.通信过程

  1. 获取ActivityManager实例: 当应用程序调用Context.getSystemService(Context.ACTIVITY_SERVICE)时,Android系统会自动处理后续的Binder通信流程。系统内部逻辑会通过servicemanager找到ActivityManagerService对应的Binder句柄。
  2. 创建并返回ActivityManagerProxy: 找到Binder句柄的同时,系统会基于这个句柄创建一个ActivityManagerProxy对象,并将其返回给调用方。ActivityManagerProxy就是一个Binder代理对象,它实现了IActivityManager接口,并且通过Binder机制将方法调用转换为跨进程通信请求,发送给系统服务端的ActivityManagerService。

ActivityManagerProxy的创建和Binder句柄的获取几乎是同步完成的,并且是系统在后台隐式进行的。当你获取到ActivityManager实例时,实际上你得到的是已经绑定了ActivityManagerService的Binder句柄的ActivityManagerProxy对象。

在通信流程中,客户端进程通过servicemanager找到ActivityManagerService对应的Binder句柄后,会创建一个ActivityManagerProxy对象,并将这个句柄绑定到代理对象上。随后,客户端通过操作这个代理对象来间接调用ActivityManagerService的方法,从而实现了跨进程的交互。

3.ActivityManagerService的Binder服务句柄

在Android系统中,ActivityManagerService的Binder服务句柄是一种用于标识和引用ActivityManagerService的唯一标识符。这个句柄在系统层面扮演着至关重要的角色:

  1. 唯一标识: Binder服务句柄就像是服务的一个身份证号,它是一个在系统内全局唯一的数字或指针,用于区分和标识不同的Binder服务。对于ActivityManagerService而言,这个句柄是用来识别和访问特定的Activity管理服务实例的关键信息。
  2. 服务定位: 当客户端(如应用程序)需要与ActivityManagerService进行通信时,它首先需要通过Binder驱动和servicemanager获取ActivityManagerService的Binder服务句柄。获取句柄后,客户端就可以通过这个句柄与服务端建立联系,请求执行特定的操作。
  3. 安全访问: 句柄的存在有助于实现安全访问控制。没有合法句柄的客户端无法直接访问ActivityManagerService。系统可以根据句柄对请求进行鉴权,确保只有具备相应权限的进程才能调用服务。
  4. 高效通信: Binder驱动使用服务句柄在内核空间中快速定位服务实体,从而实现高效的跨进程通信。通过句柄,Binder驱动能够在内核层准确地寻址和调度,执行跨进程的消息传递、数据传输等操作。
  5. 内存管理: 在Binder通信中,句柄还可以帮助内核管理与服务相关的内存资源,确保数据在进程间传递时的正确性和一致性。

总之,ActivityManagerService的Binder服务句柄是一个至关重要的抽象概念,它是Android Binder机制实现跨进程通信和系统服务管理的基础。通过句柄,客户端可以间接地访问和调用服务端的功能,从而保证了Android系统的模块化、安全性和高效性。

4.通信过程中Binder驱动的作用

  • 获取Binder句柄: 当应用程序通过Context.getSystemService(Context.ACTIVITY_SERVICE)获取ActivityManager实例时,系统内部会通过Binder驱动与servicemanager交互,请求获取ActivityManagerService的服务句柄。这时Binder驱动用于实现客户端进程与servicemanager进程之间的通信。
  • 创建Binder代理对象: 获取到ActivityManagerService的Binder句柄后,系统会基于此句柄创建一个ActivityManagerProxy对象。此时,Binder驱动并未直接参与到创建代理对象的过程中,但代理对象的创建是基于Binder通信机制的,后续对服务端的调用将依赖于Binder驱动。
  • 跨进程通信: 当应用程序通过ActivityManager实例调用任何方法时(例如查询正在运行的任务列表),实际是调用了ActivityManagerProxy的方法。此时,Binder驱动会被用到,因为它负责将客户端进程的请求通过Binder机制传输到服务端进程(即ActivityManagerService所在的system_server进程)。
  • 数据传输与控制: Binder驱动在底层实现数据的序列化、反序列化,以及必要的内存管理、错误处理、权限检查等功能,确保跨进程通信的安全性和效率。它还会负责将服务端处理后的结果数据传输回客户端进程。
  • 总的来说,Binder驱动在整个过程中贯穿始终,为Android系统中跨进程通信提供了基础的、底层的支持。它的作用在客户端与服务端首次建立连接时就开始显现,并持续作用于每次客户端对服务端的调用过程之中。

5.ActivityManagerProxy对象和Binder服务句柄

Binder服务句柄:

  • 句柄是一个数字或指针,是Binder服务在内核空间中的唯一标识符。
  • 作用在于定位服务实体,相当于一个地址标签,客户端通过句柄告诉Binder驱动应该与哪个服务实体进行通信。
  • 客户端必须先获取服务的句柄,才能发起对服务端的调用请求。

ActivityManagerProxy对象:

  • ActivityManagerProxy是运行在客户端进程中的一个代理类,它实现了与ActivityManagerService交互所需的接口(如IActivityManager)。
  • 作用在于为客户端提供一套便捷、面向对象的方法调用接口,隐藏了底层Binder通信的复杂性。
  • 当客户端通过ActivityManagerProxy调用方法时,实际上是通过持有的Binder服务句柄与服务端进行交互。

简而言之,Binder服务句柄是客户端与服务端进行通信的基础桥梁,而ActivityManagerProxy则是客户端调用服务端功能的门面,它将方法调用包装成Binder通信请求,并通过持有的Binder句柄传递给服务端。两者相辅相成,共同实现了客户端与ActivityManagerService之间的高效、安全的跨进程通信。
ActivityManagerProxy持有Binder服务句柄。当客户端通过ActivityManagerProxy与ActivityManagerService进行通信时,ActivityManagerProxy在内部构造时就已经通过Binder驱动和servicemanager获得了与ActivityManagerService关联的Binder服务句柄。在后续调用过程中,ActivityManagerProxy会使用这个句柄来发起对ActivityManagerService的Binder方法调用,从而实现客户端与服务端的通信。ActivityManagerProxy作为一个代理类,它通过持有Binder服务句柄,对外提供了一组与ActivityManagerService接口一致的方法,当客户端调用这些方法时,ActivityManagerProxy会封装调用请求,并通过Binder驱动将请求发送到服务端,最终完成跨进程通信。

6.servicemanager进程

在Android系统中,servicemanager是一个用户空间的守护进程,它维护了一份系统服务的注册表。这份注册表主要用于存放服务的名字(字符串形式)和它们对应的Binder实体的引用。当一个服务(如ActivityManagerService)启动并向servicemanager注册时,servicemanager会把这个服务的名称与其本地Binder对象的句柄关联起来。其他进程可以通过servicemanager查找和获取服务句柄,从而与服务进行交互。

总结

创建实例时:
当客户端应用程序调用Context.getSystemService(Context.ACTIVITY_SERVICE)获取ActivityManager实例时,客户端应用进程通过Binder驱动与servicemanager交互,找到ActivityManagerService对应的Binder句柄,找到Binder句柄的同时,系统会基于这个句柄创建一个ActivityManagerProxy对象,并将这个句柄绑定到ActivityManagerProxy对象上,然后将其返回给客户端应用程序。即ActivityManagerProxy持有Binder服务句柄。

调用方法时:
当客户端应用程序调用ActivityManager的方法时,实际上是通过ActivityManagerProxy向运行在 System Server 进程中的 ActivityManagerService发送请求,具体的,ActivityManagerProxy调用方法时,它会将方法调用请求以及必要参数封装,并通过Binder驱动将这个请求发送到服务端——即运行在system_server进程中的ActivityManagerService。
Binder驱动在接收到客户端发来的请求时,会根据请求中携带的Binder服务句柄找到对应的服务实体(这里是ActivityManagerService),并将请求转发给该服务实体进行处理。服务实体处理完毕后,其返回的结果也会通过Binder驱动返回给客户端进程中的ActivityManagerProxy,进而反馈给客户端调用者。

再次总结

  • BinderStub 是服务端的Binder本地对象(Local Binder Object),它实现了服务端接口,并运行在服务端进程中。当服务端注册服务时,BinderStub会被注册到Service Manager中,并与一个句柄(handle)关联。
  • BinderProxy 是客户端的Binder代理对象(Proxy Binder Object),它在客户端进程中创建,并指向服务端的BinderStub。客户端通过BinderProxy与服务端进行交互。

当客户端应用程序调用Context.getSystemService(Context.ACTIVITY_SERVICE)获取ActivityManager实例时,会经历以下步骤:

  1. 客户端通过Service Manager找到对应服务的句柄(handle)。
  2. 根据这个句柄,客户端创建一个指向服务端ActivityManagerService的BinderProxy对象(例如IActivityManager接口的Binder Proxy,通常包装为ActivityManager实例)。

当客户端应用程序调用ActivityManager实例(即ActivityManagerProxy)的方法时,会发生以下情况:
3. 客户端通过BinderProxy对象发起一个Binder事务请求,这个请求中包含了服务端句柄信息。
4. Binder驱动在收到请求后,根据客户端请求中的句柄信息在System Server进程中找到对应的ActivityManagerService的Binder本地对象(即ActivityManagerService.Stub,我们称作ActivityManagerStub)。
5. Binder驱动在System Server进程中调用ActivityManagerStub中的相应方法执行请求的操作。所以,当客户端调用ActivityManager的方法时,实际上是通过Binder驱动在System Server进程中找到了ActivityManagerStub并调用了其中的方法。

note

当客户端调用ActivityManager的方法时,实际的过程是通过Binder驱动在System Server进程中找到ActivityManagerStub并调用其中的方法,这个过程通常在一个Binder线程中完成。
在System Server进程中,系统为Binder通信分配了专门的线程池来处理这些请求。当客户端发起Binder调用时,Binder驱动会选择一个空闲的Binder线程来执行服务端(即ActivityManagerStub)的方法。这样做是为了保证并发环境下,多个客户端的请求能够并行处理,同时也确保了Binder通信不会阻塞服务端进程的主线程。
因此,每次客户端调用ActivityManager的方法时,其背后的Binder通信过程会在System Server进程中的Binder线程中完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值