Chinaunix首页 | 论坛 | 博客
  • 博客访问: 497486
  • 博文数量: 135
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 905
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-24 19:31
文章分类

全部博文(135)

文章存档

2010年(135)

我的朋友

分类: LINUX

2010-03-31 15:15:48

7月7日

Android平台——Binder机制

由代码来补充部分:

int main(int argc, char** argv)

{

    sp proc(ProcessState::self());

    sp sm = defaultServiceManager();

    LOGI("ServiceManager: %p", sm.get());

    AudioFlinger::instantiate();

    MediaPlayerService::instantiate();

    CameraService::instantiate();

    ProcessState::self()->startThreadPool();

    IPCThreadState::self()->joinThreadPool();

}

sp proc(ProcessState::self()), 这一行代码会建立ProcessState对象,这里ProcessState::self() 是一个静态变量,一个进程只有唯一的一个ProcessState对象,而ProcessState类的作 用是来打开/dev/binder设备。这也就说明了一个问题,一个进程只不可能同时存在多个对/dev/binder的操作。

sp sm = defaultServiceManager(),这一 行代码要做的事情参见上图。1、创建一个BpBinder2、由BpBinder对象创建BpServiceManger对象。(为什么要采取如此不自然的方式,可以看一下这两个对象继承的基类)。完成这一步骤的最重要 的作用在于以后对于IServiceManager对象的方法的调用,都将会由其子类BpServiceManger的方法来实现(这样做的意义何在?这样的作用仅仅在于我们可以重用IServiceManager的代码,别忘了我们还有一个类似的继承自IServiceManager的类,它叫做BnServiceManger)。这样说起来似乎过于抽象,好在我们可以举一个例子,接下去的代码就会有例子出现。

CameraService::instantiate(),这一行的代码(前面还有两行?相信我,他们绝对是几乎一样的实现,当然我是指从Binder层来说,而不是指与硬件相关的交互)。我们仍然先画出结构图:

我们需要一点代码来辅助我们的分析,CameraService::instantiate的代码如下:

void CameraService::instantiate() {

    defaultServiceManager()->addService(

            String16("media.camera"), new CameraService());

}

仍然是由defaultServiceManager函数开始,但是我们此时已经拥有了对象,而这样做的目的仅仅在于我们调用的会是BpServiceManger类中的addService方法,而不是IServiceManager基类的addService方法。我们 试着去寻找BpServiceManger类中的addService函数。在此 之前有个需要我们注意的地方new CameraService,这里实例化了一个CameraService对象,他的基类们是我们要注意的,因为之后我们将不得不关注于整套虚函数调用的机制。CameraService类的继承关系我在图中已经画出:IBinder->BBinder(ICmaerService两个基类)->BnInterface->BnCamerService->CamerService,看起来足够复杂,不幸的是这个继承模式是有意义的。

我们将思路再拉回来,接着看BpServiceManger类中addService的实现:

virtual status_t addService(const String16& name, const sp& service)

{

        Parcel data, reply;

        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

        data.writeString16(name);

        data.writeStrongBinder(service);

        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

        return err == NO_ERROR ? reply.readInt32() : err;

}

Data.writeInterfaceTokendata.writeString这 两行我们无需关注,因为它们完成一些接口命名之类的事情。来看看data.writeStrongBinder会做些什么:

status_t Parcel::writeStrongBinder(const sp& val)

{

    return flatten_binder(ProcessState::self(), val, this);

}

flatten_binder代码 如下:

status_t flatten_binder(const sp& proc,

    const sp& binder, Parcel* out)

{

    flat_binder_object obj;

   

    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

    if (binder != NULL) {

        IBinder *local = binder->localBinder();

        if (!local) {

            BpBinder *proxy = binder->remoteBinder();

            if (proxy == NULL) {

                LOGE("null proxy");

            }

            const int32_t handle = proxy ? proxy->handle() : 0;

            obj.type = BINDER_TYPE_HANDLE;

            obj.handle = handle;

            obj.cookie = NULL;

        } else {

            obj.type = BINDER_TYPE_BINDER;

            obj.binder = local->getWeakRefs();

            obj.cookie = local;

        }

    } else {

        obj.type = BINDER_TYPE_BINDER;

        obj.binder = NULL;

        obj.cookie = NULL;

    }

   

    return finish_flatten_binder(binder, obj, out);

}

我们先来关注IBinder *local = binder->localBinder()这一行代码,binder变量是一个IBinder类的指针,那么是否是说我们要调用的是IBinder类的localBinder函数呢?我去查看代码,发现它是一个虚函数,说明我们将会调用的是指针指向的对象的localBinder函数。还没忘记我们刚才特别提到的地方吧?defaultServiceManager()->addService(String16("media.camera"), new CameraService());它是一个CamerService对象,理论上来说我们应该是按照沿基类向上的方式查找实现,CamerService-> BnCamerService->BnInterface->ICmaerServiceBBinder两个基类-> IBinder这样的查找顺序。我们在BBinder类的实现中找到了这个localBinder这个函数,那么这里将会调用的就是BBinder对象的实现:

BBinder* BBinder::localBinder()

{

    return this;

}很明显代码接着会走到橙色部分。

那么finish_flatten_binder又会做些什么呢?代码我就不贴了,它的作用是更新相应的数据偏移量指针。但是写到这里,我们似乎越看越糊涂,这些步骤有什么意义?Parcel类为什么又突然出现了?我们来做一下补充,首先是Parcel类的作用,它是用来完成数据的序列化的,也就是完成数据投递之前的准备工作的。投递的数据都会放在这 个类的一个实例中。我去查找Parcel类的定义的时候发现它没有虚函数,也就是说关于投递数据序列化的操作都会在这个类及其实现中完成。 我们终于可以暂时的摆脱那些虚函数们了。

我们的工作还远没有结束,我们还没有看到数据是如何投递的?那么我们接着来看addService函数中的最后一个函数调用remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply),它明显是用来投递数 据的,如何投递?这里我们要弄清楚两个问题:1remote函数返回的是什么?也就是transcat是哪个对象的方法。2transcat如何与底层交互。

我们先来看看第一个问题。先前已经讨论过,addService方法的调用是来自BpServiceManager对象,我们忘了给出另一套类继承的机制:RefBase->IServiceManagerBpRefBase两个基类->BpInterface->BpServiceManager 那么这里的remote方法(与addService一样均属于BpServiceManager),将会调用BpServiceManager的基类BpRefBaseremote方法。其实现时:inline  IBinder*   remote()   { return mRemote; }。 问题在于这里的mRemote会是BBinder呢还是BpBinder?这个讨论使得我们不得不又再次回到之前的代码中去(确实复杂,但还不至于会使人疑惑。)答案在很早 以前的defaultServiceManager函数中,之前我们并没有分析过这个函数,是因为我们之前并不需要知道这个函数太多的细节,我们只用 知道它是为了完成BpServiceManger对象的建立,但实际上,它还完成了另一个功能,将BpRefBased对象的mRemote成员初始化为BpBinder对象。来看代码:

sp defaultServiceManager()

{

    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

   

    {

        AutoMutex _l(gDefaultServiceManagerLock);

        if (gDefaultServiceManager == NULL) {

            gDefaultServiceManager = interface_cast(

                ProcessState::self()->getContextObject(NULL));

        }

    }

   

    return gDefaultServiceManager;

}

ProcessState::self()->getContextObject 此函数返回一个BpBinder对象,当然这个对象的指针是其基类指针IBander。然后由interface_cast再次调用,而为mRemote成员的赋值也同样发生在BpServiceManger对象的建立之时,调用BpServiceManger类的构造函数:    BpServiceManager(const sp& impl): BpInterface(impl),再次调用BpInterface类的构造函数

template

inline BpInterface::BpInterface(const sp& remote)

    : BpRefBase(remote)

就在绿色的代码部分了,具体的分析请看另一篇文档,这里只是补充。

第一个问题,为我们指明了方向,也就是通讯的时候会采用BpBinder对象的transact函数。这样我们来 继续看一下第二个问题,现在我们直奔BpBinder类中的transact函数的实现:

status_t BpBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    // Once a binder has died, it will never come back to life.

    if (mAlive) {

        status_t status = IPCThreadState::self()->transact(

            mHandle, code, data, reply, flags);

        if (status == DEAD_OBJECT) mAlive = 0;

        return status;

    }

 

    return DEAD_OBJECT;

}

 

今天只能写这么多,binder机制的路还很长很 长!

阅读(1943) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~