隔行如隔山,这句话一样适用于任什么时候候,即时同一个专业,深刻下去的话,差异也是巨大的。今天,讲下本身如何学习binder进程间通讯的机制的一些看法。开始的时候,只知道 Binder 是个很底层的东西,甚至对于具体是什么用都不是很清楚。java
主要是经过两种方式:android
看别人写的Binder博文
目的很简单,大概了解Binder是个什么东西,有哪些核心的东西,对于看源码的时候选择性过滤有帮助,最好是看了后画下思惟导图总结下或者能够画下流程图。c++
看Binder源码
对于切入点的话,从最熟悉的客户端入手;选择典型的具体例子,分析下前面从他人那边看到的重点。git
想下若是两个进程须要相互通讯,须要作什么? 假设其中一个进程是客户端进程,另外一个是服务端进程,这里约定简称客户端与服务端。数组
1.客户端须要知道哪个是他要调用的服务端的方法。
2.客户端如何传递和接收数据给服务端。
3.屏蔽底层通讯的细节,包括数据交换经过共享内存。
第一个问题很简单,搞一个惟一的标识符,经过包名+类名。
第二个问题,可使用实现Parcelable接口的类,why? 这是由于 Android 系统可经过它将对象分解成可编组到各进程的原语。
第三个问题,封装一个类来具体的实现,他的名字叫Binder,而后这个binder的话,须要服务端来继承。缓存
[=> ActivityManagerNative::ActivityManagerProxy]架构
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, int userId) throws RemoteException { //这一步操做主要实例了两个Parcel对象,datat是客户端的发送数据,reply是服务端返回的数据 //具体参考:Parcel的obtain和recycle方法 Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); service.writeToParcel(data, 0); data.writeString(resolvedType); data.writeInt(userId); // mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); ComponentName res = ComponentName.readFromParcel(reply); //具体参考:Parcel的obtain和recycle方法 data.recycle(); reply.recycle(); return res; }
[=> Parcel.java::obtain]app
private static final int POOL_SIZE = 6; private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE]; ... ... ... /** *说明下:这个pool是上面声明的一个6容量的Parcel数组,方法中省略若干代码 *从这个pool中检索一个新的 Parcel 对象 */ public static Parcel obtain() { final Parcel[] pool = sOwnedPool; synchronized (pool) { Parcel p; for (int i=0; i<POOL_SIZE; i++) { p = pool[i]; if (p != null) { pool[i] = null; return p; } } } //这里参数传的是0 return new Parcel(0); } ... ... ... private Parcel(int nativePtr) { init(nativePtr); } private void init(int nativePtr) { if (nativePtr != 0) { mNativePtr = nativePtr; mOwnsNativeParcelObject = false; } else { //nativeCreate是个native方法,参考:nativeCreate方法,mNativePtr这个是能够理解成指针 mNativePtr = nativeCreate(); mOwnsNativeParcelObject = true; } } private void freeBuffer() { if (mOwnsNativeParcelObject) { nativeFreeBuffer(mNativePtr); } }
[=> android_os_Parcel.cpp::android_os_Parcel_create]学习
/** *这里来看的话,很清楚的看到返回的是parcel的指针 **/ static jint android_os_Parcel_create(JNIEnv* env, jclass clazz) { Parcel* parcel = new Parcel(); return reinterpret_cast<jint>(parcel); }
[=> Parcel.java::recycle]this
/** * 把一个Parcel对象放回到pool池中。在这回调以前,不须要这个对象。You must not touch * the object after this call. */ public final void recycle() { //这个方法内部调的是native方法,实际上是根据指针释放内存 freeBuffer(); final Parcel[] pool; //这里实际上是在obtain无参方法中实例化建立过程当中赋值为true if (mOwnsNativeParcelObject) { pool = sOwnedPool; } else { //mNativePtr能够看作是指向Parcel对象的指针,sHolderPool也是一个6容量的Parcel数组 mNativePtr = 0; pool = sHolderPool; } //放到缓存数组中 synchronized (pool) { for (int i=0; i<POOL_SIZE; i++) { if (pool[i] == null) { pool[i] = this; return; } } } } ... ... ... private void freeBuffer() { if (mOwnsNativeParcelObject) { nativeFreeBuffer(mNativePtr); } }
看了源码后发现,其实这个原理相似的,缓存的方式有区别,Message是经过链表方式来进行,Parcel是经过固定的数组,殊途同归之妙。
涉及代码:须要解决两个问题,一个是mRemote哪里来,另外一个是mRemote的transact方法
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
ActivityManagerProxy
类的构造方法进行赋值,而 ActivityManagerProxy(AMP)
这个类又被 asInterface
方法调用。[-> ActivityManagerNative.java::asInterface]
public abstract class ActivityManagerNative extends Binder implements IActivityManager { static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } //此处obj = BinderProxy, descriptor = "android.app.IActivityManager"; IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { //此处为null return in; } return new ActivityManagerProxy(obj); } ... }
此时obj为BinderProxy对象, 记录着远程进程system_server中AMS服务的binder线程的handle.
[-> ActivityManagerNative.java::ActivityManagerProxy]
class ActivityManagerProxy implements IActivityManager { public ActivityManagerProxy(IBinder remote){ mRemote = remote; } }
可知mRemote即是指向AMS服务的BinderProxy对象。
[-> Binder.java::BinderProxy]
final class BinderProxy implements IBinder { public native boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
mRemote实际上调用了 BinderProxy
的 transact
方法,而transact
调用了native方法mRemote.transact()
方法中,通过jni调用android_os_BinderProxy_transact
方法。
[-> android_util_Binder.cpp]
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) { ... //将java Parcel转为c++ Parcel Parcel* data = parcelForJavaObject(env, dataObj); Parcel* reply = parcelForJavaObject(env, replyObj); //gBinderProxyOffsets.mObject中保存的是new BpBinder(handle)对象 IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); ... //此处即是BpBinder::transact() status_t err = target->transact(code, *data, reply, flags); ... //最后根据transact执行具体状况,抛出相应的Exception signalExceptionForError(env, obj, err, true , data->dataSize()); return JNI_FALSE; }
gBinderProxyOffsets.mObject中保存的是BpBinder对象, 这是开机时Zygote调用AndroidRuntime::startReg方法来完成jni方法的注册.
其中register_android_os_Binder()过程就有一个初始并注册BinderProxy的操做,完成gBinderProxyOffsets的赋值过程. 接下来就进入该方法.
后续分析==