Binder解析

相关源码路径

/framework/base/core/java/Android/os/IInterface.java
/framework/base/core/java/Android/os/IServiceManager.java
/framework/base/core/java/Android/os/ServiceManager.java
/framework/base/core/java/Android/os/ServiceManagerNative.java(包含内部类ServiceManagerProxy)

/framework/base/core/java/Android/os/IBinder.java
/framework/base/core/java/Android/os/Binder.java(包含内部类BinderProxy)
/framework/base/core/java/Android/os/Parcel.java
/framework/base/core/java/com/Android/internal/os/BinderInternal.java

/framework/base/core/jni/Android_os_Parcel.cpp
/framework/base/core/jni/AndroidRuntime.cpp
/framework/base/core/jni/Android_util_Binder.cpp

       Android系统中,多进程间的通信都是依赖于底层Binder IPC机制,Binder机制是一种RPC方案例如:当进程A中的Activity与进程B中的Service通信时,就使用了binder机制。为了完成进程间的通信,binder使用AIDL来描述进程间的接口。此外,整个Android系统架构中,采用了大量的binder机制。

       Android中的Binder通信采用C/S架构,从组件视角来说,包含ClientServerService Manager以及binder驱动,其中Service Manager用于管理系统中的各种服务。Binder整体通信架构如下图所示:

 

(1)注册服务(addService):Server进程要先注册Service到Service Manager。该过程:Server是客户端,Service Manager是服务端;

(2)获取服务(getService):Client进程使用某个Service前,须先向Service Manager中获取相应的Service。该过程:Client是客户端,Service Manager是服务端;

(3)使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:client是客户端,server是服务端。

       

        binder相对来说还是比较复杂的,有framework层与native层的binder。framework层的binder采用JNI技术来调用native(C/C++ framework)层的binder架构,从而为上层应用程序提供服务。需要注意的是:

(1) framework层的Binder是建立在Native层架构基础之上的,核心逻辑都是交予Native层方法来处理

(2)framework层的Service Manager类与Native层的功能并不完全对应,java层的Service Manager类的实现最终是通过BinderProxy传递给Native层来完成的。

 

       图中红色代表整个frameworkbinder架构相关组件;Binder类代表Server端,BinderProxy类代表Client端;图中蓝色代表NativeBinder架构相关组件。


1 binder介绍

         Android源码中,binder的核心库是在native层实现,但在java层和native层都有接口供应用程序使用。如果单从binder角度出发,Binder架构图如下:

 

(1) binder驱动层

         Android因此添加了binder驱动,其设备节点为/dev/binder,主设备号为10binder驱动程序在内核中的头文件和代码路径如下:

   kernel/drivers/staging/binder.h

         kernel/drivers/staging/binder.c

         binder驱动层的主要作用是完成实际的binder数据传输。

(2) binder adapter

       主要是IPCThreadState.cppProcessState.cpp,源码位于frameworks/native/libs/binder目录下,这两个类都采用了单例模式,主要负责和驱动直接交互。

        a、ProcessState,进程相关的类,负责打开binder设备,进行一些初始化设置并做内存映射;

void ProcessState::startThreadPool()该方法启动的新线程,并通过joinThreadPool读取binder设备,查看是否有请求。

        b、IPCThreadState,线程相关的类,负责直接和binder设备通信,使用ioctl读写binder驱动数据。 

status_t IPCThreadState::talkWithDriver(bool doReceive) 该方法调用的是ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)从/dev/binder读取。
status_t IPCThreadState::executeCommand(int32_t cmd)该方法是对talkWithDriver返回的数据进行处理。
void IPCThreadState::joinThreadPool(bool isMain)该方法创建线程并进行talkWithDriver以及executeCommand。

(3) Binder核心层

       Binder核心层主要是IBinder及它的两个子类,即BBinderBpBinder,分别代表了最基本的服务端及客户端。源码位于frameworks/native/libs/binder目录下。

       binder service服务端实体类会继承BnInterface,而BnInterface会继承自BBinder,服务端可将BBinder对象注册到servicemananger进程。

       客户端程序和驱动交互时只能得到远程对象的句柄handle,它可以调用调用ProcessStategetStrongProxyForHandle函数,利用句柄handle建立BpBinder对象,然后将它转为IBinder指针返回给调用者。这样客户端每次调用IBinder指针的transact方法,其实是执行BpBindertransact方法。

(4) Binder框架层

      a、Native Binder框架层包含以下类(frameworks/native/libs/binder)IInterfaceBnInterfaceBpInterface,等。

      b、Java框架层包含以下类(frameworks/base/core/java/android/os):

      IBinderBinderIInterfaceServiceManagerNativeServiceManagerBinderInternalIServiceManagerServiceManagerProxy

     Java框架层的类的部分方法的实现在本地代码里(frameworks/base/core/jni)


1.1 Binder类分层

        整个Binderkernel至,nativeJNIFramework层所涉及的类如下:

【初始化】

         Zygote启动时会有一个虚拟机注册过程,该过程调用AndroidRuntime::startReg方法来完成jni方法的注册。调用register_Android_os_Binder完成binder的native方法注册。
int register_Android_os_Binder(JNIEnv* env)
{
    // 注册Binder类的jni方法
    if (int_register_Android_os_Binder(env) < 0)  
        return -1;

    // 注册BinderInternal类的jni方法
    if (int_register_Android_os_BinderInternal(env) < 0)
        return -1;

    // 注册BinderProxy类的jni方法
    if (int_register_Android_os_BinderProxy(env) < 0)
        return -1;              
    ...
    return 0;
}


1.2 binder调用顺序

          使用AIDL进行跨进程的通信,实际上就是使用binder,必须要继承binder接口,java和C++都有对应的IBinder,proxy,stub等,通过jni进程数据的交互,binder的核心在native层。整个调用关系如下。




2 Binder的Proxy-Stub模式


2.1 Java空间      


        IBinder/Binder/BinderProxy是Binder机制的核心api, 而IInterface和AIDL就是为了方便开发者使用Binder进行进程间通信。先看IBinder接口:

public interface IBinder 
{
    . . . . . .
    public String getInterfaceDescriptor() throws RemoteException;
    public boolean pingBinder();
    public boolean isBinderAlive();
    public IInterface queryLocalInterface(String descriptor);  //返回IInterface类型
    public void dump(FileDescriptor fd, String[] args) throws RemoteException;
    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;  //通信函数
    
    public interface DeathRecipient 
    {
        public void binderDied();
    }
    public void linkToDeath(DeathRecipient recipient, int flags)throws RemoteException;
    public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}

Binder与BinderProxy的定义如下,都实现了IBinder接口
public class Binder implements IBinder {

    ...
    public Binder() {
        init();

        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Binder> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
    }
    
    public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }
    
    public String getInterfaceDescriptor() {
        return mDescriptor;
    }

    public IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

    protected boolean onTransact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (code == INTERFACE_TRANSACTION) {
            reply.writeString(getInterfaceDescriptor());
            return true;
        } else if (code == DUMP_TRANSACTION) {
            ParcelFileDescriptor fd = data.readFileDescriptor();
            String[] args = data.readStringArray();
            if (fd != null) {
                try {
                    dump(fd.getFileDescriptor(), args);
                } finally {
                    try {
                        fd.close();
                    } catch (IOException e) {
                        // swallowed, not propagated back to the caller
                    }
                }
            }
            // Write the StrictMode header.
            if (reply != null) {
                reply.writeNoException();
            } else {
                StrictMode.clearGatheredViolations();
            }
            return true;
        }
        return false;
    }
    
    public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);//调用onTransact()函数
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }
    
    public void linkToDeath(DeathRecipient recipient, int flags) {
    }

    public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
        return true;
    }
    
    protected void finalize() throws Throwable {
        try {
            destroy();
        } finally {
            super.finalize();
        }
    }

    private native final void init();
    private native final void destroy();

    // Entry point from android_util_Binder.cpp's onTransact
    private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
        ...
        try {
            res = onTransact(code, data, reply, flags);//调用onTransact()函数
        } catch (RemoteException e) {
            if ((flags & FLAG_ONEWAY) != 0) {
                Log.w(TAG, "Binder call failed.", e);
            } else {
                reply.setDataPosition(0);
                reply.writeException(e);
            }
            res = true;
        } 
        ...
        return res;
    }
}

final class BinderProxy implements IBinder {
    ...
    public IInterface queryLocalInterface(String descriptor) {
        return null;
    }

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
        return transactNative(code, data, reply, flags);
    }

    public native String getInterfaceDescriptor() throws RemoteException;
    public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;
    public native void linkToDeath(DeathRecipient recipient, int flags)
            throws RemoteException;
    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);

    BinderProxy() {
        mSelf = new WeakReference(this);
    }    
   ...
}
最后,在来看IInterface接口,很简单,就一个方法,返回值是IBinder。
public interface IInterface
{
    public IBinder asBinder();
}
四者的UML类图如下所示:


       这就是BInder机制Proxy-Stub模式原始配方。
       在这个类图的最顶层,有两个接口,IInterface和IBinder。IBinder代表跨进程传输的能力,而IInterface则用来辅助实现具体的传输业务。Binder是IBinder的实现类,因此它具备跨进程传输的能力,它实际上就是远程Server端的Binder对象本身。与此对应的BinderProxy则是远程Binder的代理对象,给Client进程用的。在跨越进程的时候,Binder驱动会自动完成这两个对象的转换。

当我们写了一个AIDL文件之后,如下:
interface ICompute {
    int add(int a,int b);
}
此时,会生成一个相应的java文件,如下:
/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\Code\\Github\\Android\\Demo\\src\\com\\tfygg\\demo\\service\\ICompute.aidl
 */
package com.tfygg.demo.service;

public interface ICompute extends android.os.IInterface {
	/** Local-side IPC implementation stub class. */
	public static abstract class Stub extends android.os.Binder implements com.tfygg.demo.service.ICompute {
		private static final java.lang.String DESCRIPTOR = "com.tfygg.demo.service.ICompute";

		/** Construct the stub at attach it to the interface. */
		public Stub() {
			this.attachInterface(this, DESCRIPTOR);
		}

		/**
		 * Cast an IBinder object into an com.tfygg.demo.service.ICompute
		 * interface, generating a proxy if needed.
		 */
		public static com.tfygg.demo.service.ICompute asInterface(android.os.IBinder obj) {
			if ((obj == null)) {
				return null;
			}
			android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
			if (((iin != null) && (iin instanceof com.tfygg.demo.service.ICompute))) {
				return ((com.tfygg.demo.service.ICompute) iin);
			}
			return new com.tfygg.demo.service.ICompute.Stub.Proxy(obj);
		}

		@Override
		public android.os.IBinder asBinder() {
			return this;
		}

		@Override
		public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
				throws android.os.RemoteException {
			switch (code) {
			case INTERFACE_TRANSACTION: {
				reply.writeString(DESCRIPTOR);
				return true;
			}
			case TRANSACTION_add: {
				data.enforceInterface(DESCRIPTOR);
				int _arg0;
				_arg0 = data.readInt();
				int _arg1;
				_arg1 = data.readInt();
				int _result = this.add(_arg0, _arg1);
				reply.writeNoException();
				reply.writeInt(_result);
				return true;
			}
			}
			return super.onTransact(code, data, reply, flags);
		}

		private static class Proxy implements com.tfygg.demo.service.ICompute {
			private android.os.IBinder mRemote;

			Proxy(android.os.IBinder remote) {
				mRemote = remote;
			}

			@Override
			public android.os.IBinder asBinder() {
				return mRemote;
			}

			public java.lang.String getInterfaceDescriptor() {
				return DESCRIPTOR;
			}

			@Override
			public int add(int a, int b) throws android.os.RemoteException {
				android.os.Parcel _data = android.os.Parcel.obtain();
				android.os.Parcel _reply = android.os.Parcel.obtain();
				int _result;
				try {
					_data.writeInterfaceToken(DESCRIPTOR);
					_data.writeInt(a);
					_data.writeInt(b);
					mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
					_reply.readException();
					_result = _reply.readInt();
				} finally {
					_reply.recycle();
					_data.recycle();
				}
				return _result;
			}
		}

		static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
	}

	public int add(int a, int b) throws android.os.RemoteException;
}
对照着生成出来的ICompute.java文件,绘制如下Binder模型图:

     上图中绿色部分就是生成的java文件的内容,我们发现AIDL的Binder模型是基于原始配方的扩展。当我们写完ICompute.aidl之后,ICompute,Stub,Proxy已经自动生成出来,其作用如下:
(1)ICompute接口继承了IInterface,并写了add(a,b)的方法,代表Server端进程具备计算两数相加的能力。此方法将在Stub的具体实现类中重写。
(2)Stub是一个抽象类,他本质是一个Binder,他存在的目的之一是约定好asInterface,asBinder,onTransact方法,减少我们开发具体Binder对象的工作量。此外,Stub即需要跨进程传输,又需要约定远端服务端具备的能力,因此他需要同时实现IInterface和IBinder接口,通过上文的类图可以看得出来。
(3)Proxy是代理对象,它在Client进程中使用,它持有BinderProxy对象,BinderProxy能帮我们访问服务端Binder对象的能力。

2.1 C空间

       在C空间中,仍然是一样的Binder配方,不同的是,C空间没有了AIDL,而是使用模板辅助实现了Proxy-stub。所以,在C空间中也有IBinder.h,Binder。UML类图如下:


      先看IBinder,其定义截选如下:
class IBinder : public virtual RefBase
{
public:
    . . . . . .
    IBinder();
    virtual sp<IInterface>  queryLocalInterface(const String16& descriptor);
    virtual const String16& getInterfaceDescriptor() const = 0;

    virtual bool            isBinderAlive() const = 0;
    virtual status_t        pingBinder() = 0;
    virtual status_t        dump(int fd, const Vector<String16>& args) = 0;
    virtual status_t        transact(uint32_t code, const Parcel& data,
                                     Parcel* reply, uint32_t flags = 0) = 0;

    class DeathRecipient : public virtual RefBase
    {
    public:
        virtual void binderDied(const wp<IBinder>& who) = 0;
    };
    virtual status_t        linkToDeath(const sp<DeathRecipient>& recipient,
                                        void* cookie = NULL, uint32_t flags = 0) = 0;
    virtual status_t        unlinkToDeath(const wp<DeathRecipient>& recipient,
                                          void* cookie = NULL, uint32_t flags = 0,
                                          wp<DeathRecipient>* outRecipient = NULL) = 0;

    virtual bool            checkSubclass(const void* subclassID) const;
    
    typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
    virtual void            attachObject(const void* objectID, void* object,
                                         void* cleanupCookie, object_cleanup_func func) = 0;
    virtual void*           findObject(const void* objectID) const = 0;
    virtual void            detachObject(const void* objectID) = 0;

    virtual BBinder*        localBinder();
    virtual BpBinder*       remoteBinder();

protected:
    virtual          ~IBinder();
private:
};
有接口必然有实现,BBinder和BpBinder都是IBinder的实现类,这里就总结一下他们的区别:

(1)pingBinder, BBinder直接返回OK,而BpBinder需要运行一个transact函数,这个函数很重要。
(2)linkToDeath()是用来在服务挂的时候通知客户端的,那服务端当然不需要自己监视自己咯,所以BBinder直接返回非法,而Bpbinder需要通过requestDeathNotification()要求某人完成这个事情。

        奇怪的是BBinder和BpBinder都没有实现queryLocalInterface() 接口啊,那肯定另有他人实现这个类了,这个人就是IInterface.h。客户程序通过queryLocalInterface() 可以知道服务端都提供哪些服务。
       在IInterface.h中定义的BnInterface和BpInterface是两个重要的模版,这是为各种程序中使用的。
template  
class BnInterface : public INTERFACE, public BBinder  
{  
public:  
    virtual sp  queryLocalInterface(const String16& _descriptor);  
    virtual String16        getInterfaceDescriptor() const;  
protected:  
    virtual IBinder*        onAsBinder();  
};  
     BnInterface模版的定义如下所示:  
template  
class BpInterface : public INTERFACE, public BpRefBase  
{  
public:  
                            BpInterface(const sp& remote);  
protected:  
    virtual IBinder*    onAsBinder();  
};  
        这两个模版在使用的时候,起到得作用实际上都是双继承:使用者定义一个接口INTERFACE,然后使用BnInterface和BpInterface两个模版结合自己的接口,构建自己的BnXXX和BpXXX两个类。
        DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE两个宏用于帮助BpXXX类的实现:
#define DECLARE_META_INTERFACE(INTERFACE)                               /  
    static const String16 descriptor;                                   /  
    static sp asInterface(const sp& obj);        /  
    virtual String16 getInterfaceDescriptor() const;                    /  
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       /  
    const String16 I##INTERFACE::descriptor(NAME);                      /  
    String16 I##INTERFACE::getInterfaceDescriptor() const {             /  
        return I##INTERFACE::descriptor;                                /  
    }                                                                   /  
    sp I##INTERFACE::asInterface(const sp& obj)  /  
    {                                                                   /  
        sp intr;                                          /  
        if (obj != NULL) {                                              /  
            intr = static_cast(                          /  
                obj->queryLocalInterface(                               /  
                        I##INTERFACE::descriptor).get());               /  
            if (intr == NULL) {                                         /  
                intr = new Bp##INTERFACE(obj);                          /  
            }                                                           /  
        }                                                               /  
        return intr;                                                    /  
    }  
       在定义自己的类的时候,只需要使用DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE两个接口,并结合类的名称,就可以实现BpInterface中asInterface()和getInterfaceDescriptor()两个函数。
       此外,IInterface还起到了转换的作用,IXXXService继承自IInterface,而IInterface中的asBinder()方法,会将自身,也就是IXXXService转换成一个IBinder对象,而asInterface接口则是将IIBinder转换为IXXXService接口。
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
      由此可知,使用interface_cast的作用就是将IBinder实例转化成IXXXService实例。
      
      可以看出,C空间的IBinder接口和java空间类似,下图可以看出C空间的binder的Proxy-stub模式








  • 5
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值