Binder机制原理分析(Java层)

版权声明:本文为博主原创文章,欢迎转载但需注明出处谢谢! https://blog.csdn.net/dongxianfei/article/details/53405252

1、背景

谈到Binder相信大家肯定都有所感触吧,我们平时肯定或多或少的接触一些,但是在分析Android源码之前我对其也是一头雾水,在网络上看到的关于Binder的文章也是似懂非懂,因为目前网络上关于Binder的文章大部分都是从C开始讲起的,对于我这个应用上层的人来说根本就没有心情看下去。
今天,通过我对源码的理解以及网络上关于Binder机制的介绍来简单的分析一下Binder在java层的原理,我们来一起学习一下吧,相信大家一定会有所收获的。

2、Binder机制

首先我们需要了解一下什么是Binder?Binder是Android跨进程通信方式,它实现了IBinder接口,是ServiceManager连接各种Manager(如WindowManager、ActivityManager等)的桥梁。如果大家想看一下Binder的示例,可以去看另外一篇文章常用Manager与ServiceManager通信分析

Binder是Android系统中非常重要的一种IPC机制,如果你想研究Frameworks,必须先对Binder机制有一定的认识,上述四个部分分别在不同的进程中,他们之间的交互都是通过Binder实现,现在我们站在宏观的角度来看Binder机制,我们先看一张图。

Binder宏观图1

3、Binder的C/S架构

其实Binder是一种基于C/S的架构,主要包含四个部分:服务端(Server),客户端(Client),Binder驱动,ServiceManager。

当一个服务进程启动后,需要将其中的Service注册到ServiceManager中,客户端想要具体的Service直接在ServiceManager中查找即可,查到具体的Service引用后即可向服务端发送请求,服务端执行完成后就返回。
即Client要想和Service交互,需要向ServiceManager申请获得该Service在Binder中的引用,并存放在自身的mRemote变量中,之后通过mRemote调用,如下图所示:

Client与Service交互

4、Binder驱动实现原理

既然客户端持有远程进程的某个对象的引用,调用引用类的方法时远程进程中的方法也就被执行了,听到这里大家有没有觉得有点不可思议,因为不同的进程之间是不能共享资源的,也就是说客户端持有的这个对象和远程进程中的对象是两个完全不同的对象,相信大家肯定有这样的疑惑,那我们不妨看一张图。

Client远程调用Service

服务端跨进程的类都要继承Binder类。我们所持有的Binder引用(即服务端的引用)并不是实际真实的远程Binder对象,我们的引用在Binder驱动里还要做一次映射。也就是说,设备驱动根据我们的引用对象找到对应的远程进程。客户端要调用远程对象方法时,只需把数据写入到Parcel,在调用所持有的Binder引用的transact()函数,transact函数执行过程中会把参数、标识符(标记远程对象及其方法)等数据放入到Client的共享内存,Binder驱动从Client的共享内存中读取数据,根据这些数据找到对应的远程进程的共享内存,把数据拷贝到远程进程的共享内存中,并通知远程进程执行onTransact()函数,这个方法也是属于Binder类。远程进程Binder对象执行完成后,将得到的结果写入自己的共享内存中,Binder驱动再将远程进程的共享内存数据拷贝到客户端的共享内存,并唤醒客户端线程。

5、总结

到这里我们的Binder简单分析就结束啦,接下来我们总结一下,这里我们需要注意一个问题。
这里我们说一下Stub.asInterface方法,我们现在知道了Service就是一个Binder对象,一个Binder对象创建后,就会在Binder驱动中形成一个引用,客户端就是通过这个引用和服务端交互,但是如果在这个Service进程内部调用这个Service,那么就没有必要使用IPC,直接可以使用这个Service对象(Binder对象),也就是说这个函数就是对外界提供了统一的接口,不管是远程调用还是本地调用,使用的都是同样的代码,所以在XXXManager里面有一个IXXX类型的变量,如果是远程调用,那么就是Proxy类(即远程代理对象),如果是本地调用,存放的就是Stub类,我们看个示例。

public interface IWindowManager extends android.os.IInterface
{
    public static abstract class Stub extends android.os.Binder implements android.view.IWindowManager
    {
        public static android.view.IWindowManager asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            //本地调用直接返回Stub对象
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof android.view.IWindowManager))) {
                return ((android.view.IWindowManager)iin);
            }
            //远程调用将返回服务端的Proxy对象
            return new android.view.IWindowManager.Stub.Proxy(obj);
        }
    }
}
  • Server所在进程启动后,需要将其中的Service注册到ServiceManager,这样Client就可以通过ServiceManager找到对应的Binder引用。
  • 通过getSystemService获得XXXManager,在XXXManager中保存了一个IXXX变量,这个变量可能是Proxy类型,也可能是Stub类型,这个过程被asInterface方法屏蔽了。

好啦,到此Binder在Java层的原理我们就简单的梳理一遍了,我们这里所叙述的只是Binder的简单理解,如果大家想深入理解的话就自行研究一下吧。

猜你喜欢

转载自blog.csdn.net/dongxianfei/article/details/53405252