当前位置:操作系统 > 安卓/Android >>

IBinder对象在进程间传递的形式(二)

这篇文章是对IBinder对象在进程间传递的形式(一)这篇文章的补充,首先还是把service启动过程的流程图贴上来
 
 \
 
Android中主要通过2种方法来获得service IBinder:
 
1.       通过ServiceManager.getService(String Descriptor)来获得Service Manager管理的service的IBinder。
 
2.       Client获得Application Service的IBinder,如下图描述的binder service流程。
 
 
 
 
    不管哪种方法,均涉及到IBinder在不同进程间的传递,因为不论是Application Service 还是System Service,它们在注册时均会涉及到第三方进程,如Application Service注册在Acitivity Manager中(system_server进程),System Service注册在Service Manager中(servicemanager进程)。
 
    从Service Manager中获得IBinder涉及到service和servicemanager进程以及client和servicemanager进程之间的IBinder传递;
 
    获得Application Service的IBinder,更是涉及到ApplicationService和system_server进程以及client和system_server进程之间的IBinder传递,如上图所示。
 
    研究这个主题的意义在于,虽然从表面上看,在用到IBinder时,我们在应用中使用的是同一个接口,但是它的实质是怎么样的?是一套什么样的机制保证在同进程间client调用的是service的实体,而在不同进程间则是调用的service的proxy。
 
    关于Binder的传递过程,首先需要了解一个service的类图关系。下图为JNI以上的类图。涉及到JNI和JAVA层的Binder对应关系。JNI层以下的Binder不涉及到这个文章的主题。
 
    IISERVICEInte易做图ce表示aidl文件生成的或者用户自定义的当前service的接口文件,SERVICE表示当前service的实现。IISERVICEInte易做图ce.Proxy表示当前service的代理。
 
    在JNI层,JavaBBinder继承自BBinder,是Binder的实体,它是在BBinder的基础上添加了成员变量jobjectmObject,该成员变量指向JAVA的SERVICE对象。这么做的好处就是在同进程间传递时,接收方能够直接向JAVA层返回SERVICE对象。
 
    JavaBBinderHolder类,可以说是JavaBBinder类的一个容器,当JAVA层的SERVICE对象被创建时,就会相应的创建一个JavaBBinderHolder实例(android_os_Binder_init@android_util_Binder.cpp),但是只有SERVICE对象被IPC传递时,JavaBBinderHolder对象才会创建一个JavaBBinder实例(JavaBBinderHolder::get(env)@ android_util_Binder.cpp)。
 
 
 \
 
   
1.      IBinder在IPC通信中的发送过程
 
   
 
   IBinder在IPC通信中,android通过Parcel类的成员函数writeStrongBinder()写入IBinder,在向Parcel写入IBinder时,首先会判断JAVA层IBinder的类型并转化为native的IBinder类型,下面介绍它的的2种类型。
 
    android_os_Parcel_writeStrongBinder()@android_util_Binder.cpp
 
       parcel->writeStrongBinder(ibinderForJavaObject(env, object));@ android_util_Binder.cpp
 
[java]
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 

    if (obj == NULL) return NULL; 
 
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { 
        JavaBBinderHolder* jbh = (JavaBBinderHolder*) 
            env->GetIntField(obj, gBinderOffsets.mObject); 
        return jbh != NULL ? jbh->get(env) : NULL; 
    } 
 
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { 
        return (IBinder*) 
            env->GetIntField(obj, gBinderProxyOffsets.mObject); 
    } 
 
    LOGW("ibinderForJavaObject: %p is not a Binder object", obj); 
    return NULL; 

 
 
1.1  IBinder是以JavaBBinder的形式传递的,即是一个ServiceIBinder的reference。如上图中的第一个return语句。
 
这种较常见,作为传输介质的IBinder所处的service和发送方在同一进程中。
 

\ 


    Service处在Process A中,ProcessA为IBinder发送方。
 
1.2  IBinder是以BpBinder的形式传递的,即是一个ServiceIBinder的Proxy。如Service bind图中的第二个return语句。
 \
   
     Service 处在Process C中,Process A为IBinder发送方。
 
 
    这种情况比较典型的就是bindservice时会用到,如图中最后一步中AMS通知client bind成功时,传递给client的就是一个service IBinder的Proxy。作为传输介质的IBinder所处的service和发送方在不同的进程中。
 
 
 
    Kernel中,Binder Module会根据IPC通信双方是否处于同一个进程中,来设置binder object type值,下图code描述。
 
 
    当IBinder的发送方和Service在同一进程的话,那么传递给内核的binder_object的type为BINDER_TYPE_BINDER,由于IBinder发送到内核均是在进程间传递的,所以Binder Module driver会将type改为BINDER_TYPE_HANDLE.
 \
 
 
    当IBinder的发送方和Service不在同一进程的话,那么传递给内核的binder_object的type就为BINDER_TYPE_HANDLE,并且这种情况接收方和Service可能处在同一个进程中,因此当这种情况发生时,需要将其改为BINDER_TYPE_BINDER。这一点在下面会介绍。
 \
 
    IBinder发送的流程:
 
 \
 
1.      IBinder在IPC通信中的接收过程
    首先查看一下Parcel的unflatten_binder@Parcel.cpp(readStrongBinder()方易做图调用到):
 
 
[java]
status_t unflatten_binder(const sp<ProcessState>& proc, 
    const Parcel& in, sp<IBinder>* out) 

&nbs
补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,