Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的) (2)

有更好的传输性能。对比于Linux的通信机制,socket:是一个通用接口,导致其传输效率低,开销大;管道和消息队列:因为采用存储转发方式,所以至少需要拷贝2次数据,效率低;共享内存:虽然在传输时没有拷贝数据,但其控制机制复杂(比如跨进程通信时,需获取对方进程的pid,得多种机制协同操作)。

安全性更高。Linux的IPC机制在本身的实现中,并没有安全措施,得依赖上层协议来进行安全控制。而Binder机制的UID/PID是由Binder机制本身在内核空间添加身份标识,安全性高;并且Binder可以建立私有通道,这是linux的通信机制所无法实现的(Linux访问的接入点是开放的)。

对用户来说,通过binder屏蔽了client的调用server的隔阂,client端函数的名字、参数和返回值和server的方法一模一样,对用户来说犹如就在本地(也可以做得不一样),这样的体验或许其他ipc方式也可以实现,但binder出生那天就是为此而生。

Java层Binder

Java层Binder的功能,依赖于Native层Binder来实现,可以认为Java层Binder架构是Native层Binder架构的一个镜像。但是这并不影响我们分析Android Java层Binder的功能。我们用一个例子来说明这个过程。

我们在第一篇中就讲解了SystemServer这个进程,这个进程和zygote进程一起撑起了Android 世界,他们之中有一个崩溃,Android世界就会砰然倒塌。Android许多的重要的系统服务如AMS、PMS等都运行在SystemServer进程中。但是还有一个比较重要的进程ServiceManager进程(简称SM)跟zygote是兄弟进程。这个进程的作用是用来统一管理服务,如AMS。它们之间的关系如下。

Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)

我们的AMS需要向SM进程中注册信息,其他进程如果想使用AMS,那么先和ServiceManager进程进行通信查询,接着再和AMS所在SystemServer进程通信。这部分关系图如下

Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)

我们这里仅上图分析①②③中的一条道路,我们来分析③,即我们的应用进程(Client)如何与服务进程(Server)交互。

Java层的Binder,我们来看涉及的类的结构图

Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)


[IBinder.java]

public interface IBinder { //交互函数 public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException; }

我们接着来看Binder和BinderProxy 他们都声明在Binder.java中

[Binder.java]

/** Binder类 */ public class Binder implements IBinder { public final boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { ...... //这里调用了onTransact函数进行处理,一般情况下这个函数都会被它的子类重写 boolean r = onTransact(code, data, reply, flags); if (reply != null) { reply.setDataPosition(0); } return r; } } /** BinderProxy类 */ final class BinderProxy implements IBinder { public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { //直接以JNI的方式调用Native层的transact函数 return transactNative(code, data, reply, flags); } public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException; }

通用的IPC流程如下

Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)

现在假设下面一个场景,我们的应用进程即我们的App想要使用ActivityManagerService的startActivity函数(这种场景肯定有的,当我们拿到手机的时候,手机已经预装了许多App,其中Launcher App(桌面管理App)是在Android系统启动完成之后启动的第一个App,我们安装好一个应用后,点击应用图标即发出Intent,想要启动另一个App中的Activity,我们在AndroidManifest.xml中注册了Main Activity)。Launcher App所在的进程要与AMS所在的进程SystemServer进程交互。
我们来看这个例子。按照上面的通用流程我们猜测Launcher进程与SystemServer进程交互过程也如上图所示,那么按照这个思路我们来看。分为3点:

是否存在业务函数的统一声明?

这一部分是我们的上图中的test函数所声明的类或者接口,我们的Client端代理和Server端服务都要实现这个函数。果然有
[IActivityManager.java]

public interface IActivityManager extends IInterface { public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException; ...... }

这里声明了我们将要调用的业务函数startActivity,那么接着第二点

是否存在Server端服务代理?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjpzf.html