Create Binder 对象跨进程传递原理.md

master
Omooo 5 years ago
parent 884b45508e
commit 234461c85a
  1. 183
      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<Parcel*>(nativePtr);
if(parcel!=NULL){
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if(err!=NO_ERROR){
signalExceptionForError(env, clazz, err);
}
}
}
sp<IBinder> 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<IBinder>&val){
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(sp<ProcessState>&proc, sp<IBinder>&binder, Parcel* out){
flat_binder_object obj;
IBinder *local = binder->localBinder();
obj.type = BINDER_TYPE_BINDER;
obj.cookie = reinterpret_cast<uintptr_t>(local);
return finish_flatten_binder(binder, obj, out);
}
status_t finish_flatten_binder(sp<IBinder>& 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<flat_binder_object*>(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(;offp<off_end;offp++){
fp=(struct flat_binder_object *)(t->buffer->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<Parcel*>(nativePtr);
if(parcel!=NULL){
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
sp<IBinder> Parcel::readStrongBinder() const{
sp<IBinder> val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
}
status_t unflatten_binder(sp<ProcessState>& proc, Parcel& in,sp<IBinder>* out){
const flat_binder_object* flat = in.readObject(false);
switch(flat->type){
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return ...;
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return ...;
}
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){
sp<IBinder> 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<IBinder>& val){
if(val->checkSubclass(&gBinderOffsets)){
jobject object = static_cast<JavaBBinder*>(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
Loading…
Cancel
Save