我记得Android中的Intent传递数据时,都基于序列化。 那么,也就是说,发送方的数据会被备份一份,然后传给接受方。 这样,大数据量的场合不适合。问题是, 我不知道Android架构的核心机制,Binder IPC进行远程调用时,调用参数究竟是如何传递的,也是进行备份后传递给远程, 还是直接共享本进程的内容给远程进程,从而使得不需要大数据量的备份和传送??  比如, 利用Binder机制, 客户端需要调用Server端的一个API,其中输入参数中包含一个指向Client进程中的一块大数据量Buffer,如1MB, 那么,此时调用时,底层的Parcel是怎么传递的, 是将Client中的这1MB进行复制再共享给Server进程吗? 还是,直接将该地址指正共享给Server进程,让其直接访问??
希望大虾解答一下~~~谢谢~~~

解决方案 »

  1.   

    以我个人的理解 , 是直接共享的方式进行数据传递的 , 因为整个IPC机制的核心是Binder驱动, 而它的实质是模拟一个虚拟设备出来 , 是基于设备节点的 , 每当有新的Service注册 , Binder驱动都会为它开辟一个节点出来 。而Client与Service之间的通信 , 表面上是通过Binder驱动来进行传递 ,而其实真正Service的管理都是由Serivce Manager来对节点进行维护和调度。而IPCThreadState::transact()中传递的数据由Parcle作为容器进行传递的 , 我个人感觉是都只是传递的状态 ,而具体的数据共享而是通过ServiceManager对节点的调用来进行的。
      

  2.   

    ServiceManager仅仅完成名字服务的功能,有了它,就可以注册服务,并在运行时查询服务了,一旦查询得到远程对象的IBind,就和ServiceManager没有任何关系了。所以,真正的远程调用和数据传递,都是在Binder驱动中完成的~~~
      

  3.   

    是的 , 主要就是通过IBinder接口 ,实际上的传递是驱动没错 , 但我觉得整个机制其实是Manager在维护的。
      

  4.   

    正在看binder,好像是通过 MemoryHeapBase 来共享内存的,具体还再看
      

  5.   

    核心是在底层的Binder,ServiceMgr仅仅是实现动态服务查询的功能。
    理论上,任何Server只要将其Binder加入Binder驱动, 然后Client在运行时只要能得到Server的Binder,即可创建出BpService,然后就可以远程调用了。  关键是,Client运行时不可能动态的获取Service的Binder, 所以需要ServiceManager的介入~~~
      

  6.   

    没有备份,Parcel在read和write的时候都是在native用指针,或者直接用memcopy来实现的status_t Parcel::writeCString(const char* str)
    {
        return write(str, strlen(str)+1);
    }status_t Parcel::write(const void* data, size_t len)
    {
        void* const d = writeInplace(len);
        if (d) {
            memcpy(d, data, len);
            return NO_ERROR;
        }
        return mError;
    }
      

  7.   

    研究了几天,终于搞定了,就是用的 MemoryHeapBase 来共享内存的。
    服务器端通过 Parcel 的 writeStrongBinder(const sp<IBinder>& val); 来传递 sp<MemoryHeapBase>
    a、服务端从ashmem中分配内存空间
        memHeap = new MemoryHeapBase(size, 0, "elf mem heap");
        memBase = new MemoryBase(memHeap, 0, size);
    b、服务端返回共享内存memHeap
        reply->writeStrongBinder(memBase->getMemory(&offset, &size)->asBinder());
        reply->writeInt32(offset);
        reply->writeInt32(size);
    c、客户端读取共享内存IMemoryHeap
        sp<IBinder> heap = reply.readStrongBinder();
        ssize_t o = reply.readInt32();
        size_t s = reply.readInt32();
        sp<IMemoryHeap> mHeap = interface_cast<IMemoryHeap> (heap);
    d、客户端使用共享内存
        char * buf = static_cast<char *> (mHeap->base());
        memset(&buf[offset], i, size);
      

  8.   

    binder是跨进程的。一样要拷贝数据。
      

  9.   

     MemoryHeapBase 是在ashmem中分配的匿名共享大内存,按我上面的方法是不会拷贝数据的。
    audoi 和 camera 就是采用的这种方式将数据提供给客户端的。
      

  10.   

    Binder没必要传递数据啊, 他的主要作用还是RPC,也就是远程函数调用,通过proxy来使用服务进程的类和方法就可以了,干嘛要拷贝啊。 如果要共享,处理大的数据,一定要使用share memroy啊
      

  11.   

    讨论的就是如何共享吧,
    BINDER 通过 PARCEL 传递的参数一般都是小的,如果要从摄像头服务端读取一张图片,用的就是传递的共享内存地址
    我想,使用LINUX的命名内存共享也应该是可以的吧,没试过。
      

  12.   

    太深入了,靠,我还在学习什么是Binder,什么IPC、AIDL和Bundle,呵呵.......谁能帮我解释下上面这四个名称的概念和用法,以及他们的实现