From 234461c85a79558e17f403b5aa792c3cddb96ad3 Mon Sep 17 00:00:00 2001 From: Omooo <869759698@qq.com> Date: Sat, 28 Mar 2020 15:55:03 +0800 Subject: [PATCH] =?UTF-8?q?Create=20Binder=20=E5=AF=B9=E8=B1=A1=E8=B7=A8?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E4=BC=A0=E9=80=92=E5=8E=9F=E7=90=86.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Binder 对象跨进程传递原理.md | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 blogs/Android/Framework/Interview/进程间通信相关/Binder 对象跨进程传递原理.md diff --git a/blogs/Android/Framework/Interview/进程间通信相关/Binder 对象跨进程传递原理.md b/blogs/Android/Framework/Interview/进程间通信相关/Binder 对象跨进程传递原理.md new file mode 100644 index 0000000..73a3207 --- /dev/null +++ b/blogs/Android/Framework/Interview/进程间通信相关/Binder 对象跨进程传递原理.md @@ -0,0 +1,183 @@ +--- +Binder 对象跨进程传递的原理是怎样的? +--- + +1. binder 传递有哪些方式? +2. binder 在传递过程中是怎么存储的? +3. binder 对象序列化和反序列化过程? +4. binder 对象传递过程中驱动层做了什么? + +先从 AIDL 入口: + +```java +interface IRemoteCaller{ + void publishBinder(ICallback callback); +} +``` + +```java +public void publishBinder(ICallback callback){ + Parcel_data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try{ + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeStrongBinder(callback!=null?callback.asBinder():null); + mRemote.transact(Stub.TRANSACTION_publishBinder, _data, _reply, 0); + _reply.readException(); + }finally{ + _reply.recycle(); + _data.recycle(); + } +} +``` + +```java +public boolean onTransact(int code, Parcel data, Parcel reply, int flags){ + String descriptor = DESCRIPTOR; + switch(code){ + case TRANSACTION_publishBinder:{ + data.enforceInterface(descriptor); + ICallback _arg0; + _arg0 = ICallback.Stub.asInterface(data.readStrongBinder()); + this.publishBinder(_arg0); + reply.writeNoException(); + return true; + } + } +} +``` + +```java +public final void writeStrongBinder(IBinder val){ + nativeWriteStrongBinder(mNativePtr, val); +} +void Parcel writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object){ + Parcel* parcel = reinterpret_cast(nativePtr); + if(parcel!=NULL){ + const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); + if(err!=NO_ERROR){ + signalExceptionForError(env, clazz, err); + } + } +} +sp ibinderForJavaObject(JNIEnv* env, jobject obj){ + if(env->IsInterfaceOf(obj, gBinderOffsets.mClass)){ + env->GetLongField(obj, gBinderOffsets.mObject); + return jbh!=NULL?jbh->get(env, obj):NULL; + } + if(env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)){ + return (IBinder*) + env->GetLongField(obj, gBinderProxyOffsets.mObject); + } + return NULL; +} +``` + +```c++ +status_t Parcel:writeStrongBinder(const sp&val){ + return flatten_binder(ProcessState::self(), val, this); +} +status_t flatten_binder(sp&proc, sp&binder, Parcel* out){ + flat_binder_object obj; + IBinder *local = binder->localBinder(); + obj.type = BINDER_TYPE_BINDER; + obj.cookie = reinterpret_cast(local); + return finish_flatten_binder(binder, obj, out); +} +status_t finish_flatten_binder(sp& binder, flat_binder_object& flat, Parcel* out){ + return out->writeObject(flat, false); +} +status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData){ + *reinterpret_cast(mData+mDataPos)=val; + mObjectsSize++; + return finishWrite(sizeof(flat_binder_object)); +} +status_t Parcel::finishWrite(size_t len){ + mDataPos += len; + return NO_ERROR; +} +``` + +Parce 到了驱动层是如何处理的? + +```c++ +static void binder_transaction(struct binder_proc *proc, ...){ + for(;offpbuffer->data+*offp); + switch(fp->type){ + case BINDER_TYPE_BINDER:{ + struct binder_node *node = binder_get_node(proc, fp->binder); + if(node==NULL){ + node=binder_new_node(proc,fp->binder,fp->cookie); + } + ref = binder_get_ref_for_node(target_proc,node); + if(fp->type==BINDER_TYPE_BINDER) + fp->type=BINDER_TYPE_HANDLE; + fp->handle=ref->desc; + }break; + } + } +} +``` + +读: + +```java +public final IBinder readStrongBinder(){ + return nativeReadStrongBinder(mNativePtr); +} +``` + +```c++ +jobject Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr){ + Parcel* parcel = reinterpret_cast(nativePtr); + if(parcel!=NULL){ + return javaObjectForIBinder(env, parcel->readStrongBinder()); + } + return NULL; +} +sp Parcel::readStrongBinder() const{ + sp val; + unflatten_binder(ProcessState::self(), *this, &val); + return val; +} +status_t unflatten_binder(sp& proc, Parcel& in,sp* out){ + const flat_binder_object* flat = in.readObject(false); + switch(flat->type){ + case BINDER_TYPE_BINDER: + *out = reinterpret_cast(flat->cookie); + return ...; + case BINDER_TYPE_HANDLE: + *out = proc->getStrongProxyForHandle(flat->handle); + return ...; + } +} +sp ProcessState::getStrongProxyForHandle(int32_t handle){ + sp result; + handle_entry* e = lookupHandleLocked(handle); + IBinder* b = e->binder; + if(b == NULL){ + b = new BpBinder(handle); + e->binder = b; + result = b; + } + return result; +} +jobject javaObjectForIBinder(JNIEnv* env, const sp& val){ + if(val->checkSubclass(&gBinderOffsets)){ + jobject object = static_cast(val.get())->object(); + return object; + } + object = env->NewObject(gBinderProxyOffsets.mClass, ...); + env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get()); + return object; +} +``` + +#### binder 是怎么跨进程传输的? + +1. Parcel 的 writeStrongBinder 和 readStrongBinder +2. binder 在 Parcel 中存储原理,flat_binder_object +3. 说清楚 binder_node,binder_ref +4. 目标进程根据 binder_ref 的 handle 创建 BpBinder +5. 由 BpBinder 再往上到 BinderProxy 到业务层的 Proxy \ No newline at end of file