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架构,从组件视角来说,包含Client、Server、Service 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层来完成的。
图中红色代表整个framework层binder架构相关组件;Binder类代表Server端,BinderProxy类代表Client端;图中蓝色代表Native层Binder架构相关组件。
1 binder介绍
Android源码中,binder的核心库是在native层实现,但在java层和native层都有接口供应用程序使用。如果单从binder角度出发,Binder架构图如下:
(1) binder驱动层
Android因此添加了binder驱动,其设备节点为/dev/binder,主设备号为10,binder驱动程序在内核中的头文件和代码路径如下:
kernel/drivers/staging/binder.h
kernel/drivers/staging/binder.c
binder驱动层的主要作用是完成实际的binder数据传输。
(2) binder adapter层
主要是IPCThreadState.cpp和ProcessState.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及它的两个子类,即BBinder和BpBinder,分别代表了最基本的服务端及客户端。源码位于frameworks/native/libs/binder目录下。
binder service服务端实体类会继承BnInterface,而BnInterface会继承自BBinder,服务端可将BBinder对象注册到servicemananger进程。
客户端程序和驱动交互时只能得到远程对象的句柄handle,它可以调用调用ProcessState的getStrongProxyForHandle函数,利用句柄handle建立BpBinder对象,然后将它转为IBinder指针返回给调用者。这样客户端每次调用IBinder指针的transact方法,其实是执行BpBinder的transact方法。
(4) Binder框架层
a、Native Binder框架层包含以下类(frameworks/native/libs/binder):IInterface,BnInterface,BpInterface,等。
b、Java框架层包含以下类(frameworks/base/core/java/android/os):
IBinder,Binder,IInterface,ServiceManagerNative,ServiceManager,BinderInternal,IServiceManager,ServiceManagerProxy
Java框架层的类的部分方法的实现在本地代码里(frameworks/base/core/jni)。
1.1 Binder类分层
整个Binder从kernel至,native,JNI,Framework层所涉及的类如下:
【初始化】
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);}@Overridepublic android.os.IBinder asBinder() {return this;}@Overridepublic 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;}@Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}@Overridepublic 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 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& 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& who) = 0; }; virtual status_t linkToDeath(const sp& recipient, void* cookie = NULL, uint32_t flags = 0) = 0; virtual status_t unlinkToDeath(const wp& recipient, void* cookie = NULL, uint32_t flags = 0, wp* 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接口。
templateinline sp interface_cast(const sp& obj){return INTERFACE::asInterface(obj);}
由此可知,使用interface_cast的作用就是将IBinder实例转化成IXXXService实例。 可以看出,C空间的IBinder接口和java空间类似,下图可以看出C空间的binder的Proxy-stub模式 更多相关文章
- 2011.09.07(5)——— android 跨进程通信之content provider + Aut
- Android跨进程通信传输大数据
- SystemServer
- Android(安卓)5.0有哪些变化
- Fedora 12安装Android(安卓)SDK
- 无法安装ADT(无法访问https://dl-ssl.google.com/android/eclipse
- Android(安卓)横屏不重启 Activity
- Android基础系列-----------Android进程/线程管理应用示例(Androi
- android 几种发送短信的方法